Auto merge of #65288 - estebank:point-at-assoc-type, r=nikomatsakis
Point at associated type for some obligations Partially address #57663.
This commit is contained in:
commit
cf148a717a
17 changed files with 304 additions and 61 deletions
|
@ -195,8 +195,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
obligation: &PredicateObligation<'tcx>,
|
||||
error: &MismatchedProjectionTypes<'tcx>,
|
||||
) {
|
||||
let predicate =
|
||||
self.resolve_vars_if_possible(&obligation.predicate);
|
||||
let predicate = self.resolve_vars_if_possible(&obligation.predicate);
|
||||
|
||||
if predicate.references_error() {
|
||||
return
|
||||
|
@ -228,7 +227,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
&mut obligations
|
||||
);
|
||||
if let Err(error) = self.at(&obligation.cause, obligation.param_env)
|
||||
.eq(normalized_ty, data.ty) {
|
||||
.eq(normalized_ty, data.ty)
|
||||
{
|
||||
values = Some(infer::ValuePairs::Types(ExpectedFound {
|
||||
expected: normalized_ty,
|
||||
found: data.ty,
|
||||
|
@ -239,13 +239,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let msg = format!("type mismatch resolving `{}`", predicate);
|
||||
let error_id = (DiagnosticMessageId::ErrorId(271),
|
||||
Some(obligation.cause.span), msg);
|
||||
let error_id = (
|
||||
DiagnosticMessageId::ErrorId(271),
|
||||
Some(obligation.cause.span),
|
||||
msg,
|
||||
);
|
||||
let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
let mut diag = struct_span_err!(
|
||||
self.tcx.sess, obligation.cause.span, E0271,
|
||||
"type mismatch resolving `{}`", predicate
|
||||
self.tcx.sess,
|
||||
obligation.cause.span,
|
||||
E0271,
|
||||
"type mismatch resolving `{}`",
|
||||
predicate
|
||||
);
|
||||
self.note_type_err(&mut diag, &obligation.cause, None, values, err);
|
||||
self.note_obligation_cause(&mut diag, obligation);
|
||||
|
@ -532,23 +538,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
/// whose result could not be truly determined and thus we can't say
|
||||
/// if the program type checks or not -- and they are unusual
|
||||
/// occurrences in any case.
|
||||
pub fn report_overflow_error<T>(&self,
|
||||
obligation: &Obligation<'tcx, T>,
|
||||
suggest_increasing_limit: bool) -> !
|
||||
pub fn report_overflow_error<T>(
|
||||
&self,
|
||||
obligation: &Obligation<'tcx, T>,
|
||||
suggest_increasing_limit: bool,
|
||||
) -> !
|
||||
where T: fmt::Display + TypeFoldable<'tcx>
|
||||
{
|
||||
let predicate =
|
||||
self.resolve_vars_if_possible(&obligation.predicate);
|
||||
let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
|
||||
"overflow evaluating the requirement `{}`",
|
||||
predicate);
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
obligation.cause.span,
|
||||
E0275,
|
||||
"overflow evaluating the requirement `{}`",
|
||||
predicate
|
||||
);
|
||||
|
||||
if suggest_increasing_limit {
|
||||
self.suggest_new_overflow_limit(&mut err);
|
||||
}
|
||||
|
||||
self.note_obligation_cause_code(&mut err, &obligation.predicate, &obligation.cause.code,
|
||||
&mut vec![]);
|
||||
self.note_obligation_cause_code(
|
||||
&mut err,
|
||||
&obligation.predicate,
|
||||
&obligation.cause.code,
|
||||
&mut vec![],
|
||||
);
|
||||
|
||||
err.emit();
|
||||
self.tcx.sess.abort_if_errors();
|
||||
|
@ -2197,6 +2213,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::AssocTypeBound(impl_span, orig) => {
|
||||
err.span_label(orig, "associated type defined here");
|
||||
if let Some(sp) = impl_span {
|
||||
err.span_label(sp, "in this `impl` item");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,8 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
|
||||
/// #[feature(trivial_bounds)] is not enabled
|
||||
TrivialBound,
|
||||
|
||||
AssocTypeBound(/*impl*/ Option<Span>, /*original*/ Span),
|
||||
}
|
||||
|
||||
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
|
|
|
@ -548,6 +548,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
super::MethodReceiver => Some(super::MethodReceiver),
|
||||
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
|
||||
super::TrivialBound => Some(super::TrivialBound),
|
||||
super::AssocTypeBound(impl_sp, sp) => Some(super::AssocTypeBound(impl_sp, sp)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3141,6 +3141,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AssocItemsIterator<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_ids: &'tcx [DefId],
|
||||
|
|
|
@ -22,11 +22,14 @@ pub fn obligations<'a, 'tcx>(
|
|||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
|
||||
let mut wf = WfPredicates { infcx,
|
||||
param_env,
|
||||
body_id,
|
||||
span,
|
||||
out: vec![] };
|
||||
let mut wf = WfPredicates {
|
||||
infcx,
|
||||
param_env,
|
||||
body_id,
|
||||
span,
|
||||
out: vec![],
|
||||
item: None,
|
||||
};
|
||||
if wf.compute(ty) {
|
||||
debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
|
||||
let result = wf.normalize();
|
||||
|
@ -47,8 +50,9 @@ pub fn trait_obligations<'a, 'tcx>(
|
|||
body_id: hir::HirId,
|
||||
trait_ref: &ty::TraitRef<'tcx>,
|
||||
span: Span,
|
||||
item: Option<&'tcx hir::Item>,
|
||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item };
|
||||
wf.compute_trait_ref(trait_ref, Elaborate::All);
|
||||
wf.normalize()
|
||||
}
|
||||
|
@ -60,7 +64,7 @@ pub fn predicate_obligations<'a, 'tcx>(
|
|||
predicate: &ty::Predicate<'tcx>,
|
||||
span: Span,
|
||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
|
||||
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
|
||||
|
||||
// (*) ok to skip binders, because wf code is prepared for it
|
||||
match *predicate {
|
||||
|
@ -107,6 +111,7 @@ struct WfPredicates<'a, 'tcx> {
|
|||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
out: Vec<traits::PredicateObligation<'tcx>>,
|
||||
item: Option<&'tcx hir::Item>,
|
||||
}
|
||||
|
||||
/// Controls whether we "elaborate" supertraits and so forth on the WF
|
||||
|
@ -157,33 +162,162 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
/// Pushes the obligations required for `trait_ref` to be WF into
|
||||
/// `self.out`.
|
||||
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
|
||||
fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
|
||||
|
||||
let cause = self.cause(traits::MiscObligation);
|
||||
let param_env = self.param_env;
|
||||
|
||||
let item = &self.item;
|
||||
let extend_cause_with_original_assoc_item_obligation = |
|
||||
cause: &mut traits::ObligationCause<'_>,
|
||||
pred: &ty::Predicate<'_>,
|
||||
trait_assoc_items: ty::AssocItemsIterator<'_>,
|
||||
| {
|
||||
let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span));
|
||||
match pred {
|
||||
ty::Predicate::Projection(proj) => {
|
||||
// The obligation comes not from the current `impl` nor the `trait` being
|
||||
// implemented, but rather from a "second order" obligation, like in
|
||||
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
|
||||
//
|
||||
// error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
|
||||
// --> $DIR/point-at-type-on-obligation-failure.rs:13:5
|
||||
// |
|
||||
// LL | type Ok;
|
||||
// | -- associated type defined here
|
||||
// ...
|
||||
// LL | impl Bar for Foo {
|
||||
// | ---------------- in this `impl` item
|
||||
// LL | type Ok = ();
|
||||
// | ^^^^^^^^^^^^^ expected u32, found ()
|
||||
// |
|
||||
// = note: expected type `u32`
|
||||
// found type `()`
|
||||
//
|
||||
// FIXME: we would want to point a span to all places that contributed to this
|
||||
// obligation. In the case above, it should be closer to:
|
||||
//
|
||||
// error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
|
||||
// --> $DIR/point-at-type-on-obligation-failure.rs:13:5
|
||||
// |
|
||||
// LL | type Ok;
|
||||
// | -- associated type defined here
|
||||
// LL | type Sibling: Bar2<Ok=Self::Ok>;
|
||||
// | -------------------------------- obligation set here
|
||||
// ...
|
||||
// LL | impl Bar for Foo {
|
||||
// | ---------------- in this `impl` item
|
||||
// LL | type Ok = ();
|
||||
// | ^^^^^^^^^^^^^ expected u32, found ()
|
||||
// ...
|
||||
// LL | impl Bar2 for Foo2 {
|
||||
// | ---------------- in this `impl` item
|
||||
// LL | type Ok = u32;
|
||||
// | -------------- obligation set here
|
||||
// |
|
||||
// = note: expected type `u32`
|
||||
// found type `()`
|
||||
if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) {
|
||||
let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
|
||||
if let Some(impl_item) = impl_items.iter().filter(|item| {
|
||||
item.ident == trait_assoc_item.ident
|
||||
}).next() {
|
||||
cause.span = impl_item.span;
|
||||
cause.code = traits::AssocTypeBound(
|
||||
item_span,
|
||||
trait_assoc_item.ident.span,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Predicate::Trait(proj) => {
|
||||
// An associated item obligation born out of the `trait` failed to be met.
|
||||
// Point at the `impl` that failed the obligation, the associated item that
|
||||
// needed to meet the obligation, and the definition of that associated item,
|
||||
// which should hold the obligation in most cases. An example can be seen in
|
||||
// `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
|
||||
//
|
||||
// error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||
// --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
|
||||
// |
|
||||
// LL | type Assoc: Bar;
|
||||
// | ----- associated type defined here
|
||||
// ...
|
||||
// LL | impl Foo for () {
|
||||
// | --------------- in this `impl` item
|
||||
// LL | type Assoc = bool;
|
||||
// | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||
//
|
||||
// FIXME: if the obligation comes from the where clause in the `trait`, we
|
||||
// should point at it:
|
||||
//
|
||||
// error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||
// --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
|
||||
// |
|
||||
// | trait Foo where <Self as Foo>>::Assoc: Bar {
|
||||
// | -------------------------- obligation set here
|
||||
// LL | type Assoc;
|
||||
// | ----- associated type defined here
|
||||
// ...
|
||||
// LL | impl Foo for () {
|
||||
// | --------------- in this `impl` item
|
||||
// LL | type Assoc = bool;
|
||||
// | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||
if let (
|
||||
ty::Projection(ty::ProjectionTy { item_def_id, .. }),
|
||||
Some(hir::ItemKind::Impl(.., impl_items)),
|
||||
) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) {
|
||||
if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
|
||||
.filter(|i| i.def_id == *item_def_id)
|
||||
.next()
|
||||
.and_then(|trait_assoc_item| impl_items.iter()
|
||||
.filter(|i| i.ident == trait_assoc_item.ident)
|
||||
.next()
|
||||
.map(|impl_item| (impl_item, trait_assoc_item)))
|
||||
{
|
||||
cause.span = impl_item.span;
|
||||
cause.code = traits::AssocTypeBound(
|
||||
item_span,
|
||||
trait_assoc_item.ident.span,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
|
||||
if let Elaborate::All = elaborate {
|
||||
let trait_assoc_items = tcx.associated_items(trait_ref.def_id);
|
||||
|
||||
let predicates = obligations.iter()
|
||||
.map(|obligation| obligation.predicate.clone())
|
||||
.collect();
|
||||
let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates);
|
||||
.map(|obligation| obligation.predicate.clone())
|
||||
.collect();
|
||||
let implied_obligations = traits::elaborate_predicates(tcx, predicates);
|
||||
let implied_obligations = implied_obligations.map(|pred| {
|
||||
traits::Obligation::new(cause.clone(), param_env, pred)
|
||||
let mut cause = cause.clone();
|
||||
extend_cause_with_original_assoc_item_obligation(
|
||||
&mut cause,
|
||||
&pred,
|
||||
trait_assoc_items.clone(),
|
||||
);
|
||||
traits::Obligation::new(cause, param_env, pred)
|
||||
});
|
||||
self.out.extend(implied_obligations);
|
||||
}
|
||||
|
||||
self.out.extend(obligations);
|
||||
|
||||
self.out.extend(
|
||||
trait_ref.substs.types()
|
||||
.filter(|ty| !ty.has_escaping_bound_vars())
|
||||
.map(|ty| traits::Obligation::new(cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::WellFormed(ty))));
|
||||
self.out.extend(trait_ref.substs.types()
|
||||
.filter(|ty| !ty.has_escaping_bound_vars())
|
||||
.map(|ty| traits::Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::WellFormed(ty),
|
||||
)));
|
||||
}
|
||||
|
||||
/// Pushes the obligations required for `trait_ref::Item` to be WF
|
||||
|
|
|
@ -430,7 +430,7 @@ fn check_item_type(
|
|||
|
||||
fn check_impl<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &hir::Item,
|
||||
item: &'tcx hir::Item,
|
||||
ast_self_ty: &hir::Ty,
|
||||
ast_trait_ref: &Option<hir::TraitRef>,
|
||||
) {
|
||||
|
@ -445,15 +445,18 @@ fn check_impl<'tcx>(
|
|||
// therefore don't need to be WF (the trait's `Self: Trait` predicate
|
||||
// won't hold).
|
||||
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
|
||||
let trait_ref =
|
||||
fcx.normalize_associated_types_in(
|
||||
ast_trait_ref.path.span, &trait_ref);
|
||||
let obligations =
|
||||
ty::wf::trait_obligations(fcx,
|
||||
fcx.param_env,
|
||||
fcx.body_id,
|
||||
&trait_ref,
|
||||
ast_trait_ref.path.span);
|
||||
let trait_ref = fcx.normalize_associated_types_in(
|
||||
ast_trait_ref.path.span,
|
||||
&trait_ref,
|
||||
);
|
||||
let obligations = ty::wf::trait_obligations(
|
||||
fcx,
|
||||
fcx.param_env,
|
||||
fcx.body_id,
|
||||
&trait_ref,
|
||||
ast_trait_ref.path.span,
|
||||
Some(item),
|
||||
);
|
||||
for obligation in obligations {
|
||||
fcx.register_predicate(obligation);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ impl<T> Bar for Option<T> {
|
|||
impl Bar for f32 {
|
||||
//~^ ERROR the trait bound `f32: Foo` is not satisfied
|
||||
type Item = f32;
|
||||
//~^ ERROR the trait bound `f32: Foo` is not satisfied
|
||||
}
|
||||
|
||||
trait Baz<U: ?Sized> where U: Foo { }
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
trait Bar {}
|
||||
|
||||
trait Foo {
|
||||
type Assoc: Bar;
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,14 @@
|
|||
error[E0277]: the trait bound `bool: Bar` is not satisfied
|
||||
--> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
|
||||
|
|
||||
LL | type Assoc: Bar;
|
||||
| ----- associated type defined here
|
||||
...
|
||||
LL | impl Foo for () {
|
||||
| --------------- in this `impl` item
|
||||
LL | type Assoc = bool;
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,20 @@
|
|||
trait Bar {
|
||||
type Ok;
|
||||
type Sibling: Bar2<Ok=Self::Ok>;
|
||||
}
|
||||
trait Bar2 {
|
||||
type Ok;
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
struct Foo2;
|
||||
|
||||
impl Bar for Foo {
|
||||
type Ok = (); //~ ERROR type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
|
||||
type Sibling = Foo2;
|
||||
}
|
||||
impl Bar2 for Foo2 {
|
||||
type Ok = u32;
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,17 @@
|
|||
error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
|
||||
--> $DIR/point-at-type-on-obligation-failure.rs:13:5
|
||||
|
|
||||
LL | type Ok;
|
||||
| -- associated type defined here
|
||||
...
|
||||
LL | impl Bar for Foo {
|
||||
| ---------------- in this `impl` item
|
||||
LL | type Ok = ();
|
||||
| ^^^^^^^^^^^^^ expected u32, found ()
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
|
@ -10,8 +10,8 @@ impl<T> Partial<T> for T::Assoc where
|
|||
{
|
||||
}
|
||||
|
||||
impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
|
||||
type Assoc = T;
|
||||
impl<T> Complete for T {
|
||||
type Assoc = T; //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-43784-associated-type.rs:13:9
|
||||
--> $DIR/issue-43784-associated-type.rs:14:5
|
||||
|
|
||||
LL | type Assoc: Partial<Self>;
|
||||
| ----- associated type defined here
|
||||
...
|
||||
LL | impl<T> Complete for T {
|
||||
| - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
| |
|
||||
| help: consider restricting this bound: `T: std::marker::Copy`
|
||||
| ----------------------
|
||||
| | |
|
||||
| | help: consider restricting this bound: `T: std::marker::Copy`
|
||||
| in this `impl` item
|
||||
LL | type Assoc = T;
|
||||
| ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ struct ParentWrapper<T>(T);
|
|||
|
||||
impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
//~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
type Ty = A;
|
||||
type Assoc = ChildWrapper<T::Assoc>;
|
||||
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
//~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -9,25 +9,31 @@ LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
|||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | type Ty = A;
|
||||
LL | | type Assoc = ChildWrapper<T::Assoc>;
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
|
||||
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:17:28
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:20:5
|
||||
|
|
||||
LL | type Assoc: Child<Self::Ty>;
|
||||
| ----- associated type defined here
|
||||
...
|
||||
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
| ^^^^^^ - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
|
||||
| |
|
||||
| the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
| ------------------------------------------------------- help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
|
||||
| |
|
||||
| in this `impl` item
|
||||
...
|
||||
LL | type Assoc = ChildWrapper<T::Assoc>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Child<A>` for `ChildWrapper<<T as Parent>::Assoc>`
|
||||
|
||||
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:21:5
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:20:5
|
||||
|
|
||||
LL | trait Parent {
|
||||
| ------------ required by `Parent`
|
||||
|
|
|
@ -27,8 +27,8 @@ struct SalsaStorage {
|
|||
_parse: <ParseQuery as Query<RootDatabase>>::Data, //~ ERROR overflow
|
||||
}
|
||||
|
||||
impl Database for RootDatabase { //~ ERROR overflow
|
||||
type Storage = SalsaStorage;
|
||||
impl Database for RootDatabase {
|
||||
type Storage = SalsaStorage; //~ ERROR overflow
|
||||
}
|
||||
impl HasQueryGroup for RootDatabase {}
|
||||
impl<DB> Query<DB> for ParseQuery
|
||||
|
|
|
@ -7,10 +7,15 @@ LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
|
|||
= note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `RootDatabase: SourceDatabase`
|
||||
--> $DIR/cycle-cache-err-60010.rs:30:6
|
||||
--> $DIR/cycle-cache-err-60010.rs:31:5
|
||||
|
|
||||
LL | type Storage;
|
||||
| ------- associated type defined here
|
||||
...
|
||||
LL | impl Database for RootDatabase {
|
||||
| ^^^^^^^^
|
||||
| ------------------------------ in this `impl` item
|
||||
LL | type Storage = SalsaStorage;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
|
||||
= note: required because it appears within the type `SalsaStorage`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue