diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-10-10 16:20:42 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-10-22 12:42:15 -0700 |
| commit | 58c6591cde1b8a54dbc1ad1b7ac64133835ec154 (patch) | |
| tree | ba64f7bf50e9c354c726b5cd9997a116c5f3b424 /src | |
| parent | 57bfb8096295150c06559da10adc5629e445a4ac (diff) | |
| download | rust-58c6591cde1b8a54dbc1ad1b7ac64133835ec154.tar.gz rust-58c6591cde1b8a54dbc1ad1b7ac64133835ec154.zip | |
Point at associated type for some obligations
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/traits/error_reporting.rs | 6 | ||||
| -rw-r--r-- | src/librustc/traits/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/traits/structural_impls.rs | 1 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc/ty/wf.rs | 64 | ||||
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-43784-associated-type.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-43784-associated-type.stderr | 17 | ||||
| -rw-r--r-- | src/test/ui/traits/cycle-cache-err-60010.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/traits/cycle-cache-err-60010.stderr | 12 |
10 files changed, 93 insertions, 41 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index daa4a215a23..7ab907701bf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2199,6 +2199,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"); + } + } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d96330bf0a9..9640a8a29d1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -268,6 +268,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. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index dab62a6bcb5..f81d4b3ca30 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -544,6 +544,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)), } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d377b7328e8..d81f5e40701 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3139,6 +3139,7 @@ impl<'tcx> TyCtxt<'tcx> { } } +#[derive(Clone)] pub struct AssocItemsIterator<'tcx> { tcx: TyCtxt<'tcx>, def_ids: &'tcx [DefId], diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index ecb075e30b1..ce92fd82761 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -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,54 @@ 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 obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); - + let assoc_items = self.infcx.tcx.associated_items(trait_ref.def_id); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; if let Elaborate::All = elaborate { let predicates = obligations.iter() - .map(|obligation| obligation.predicate.clone()) - .collect(); + .map(|obligation| obligation.predicate.clone()) + .collect(); let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + let item_span: Option<Span> = self.item.map(|i| i.span); + let item = &self.item; let implied_obligations = implied_obligations.map(|pred| { - traits::Obligation::new(cause.clone(), param_env, pred) + let mut cause = cause.clone(); + if let ty::Predicate::Trait(proj) = &pred { + if let ( + ty::Projection(ty::ProjectionTy { item_def_id, .. }), + Some(hir::ItemKind::Impl(.., bounds)), + ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { + if let Some((bound, assoc_item)) = assoc_items.clone() + .filter(|i| i.def_id == *item_def_id) + .next() + .and_then(|assoc_item| bounds.iter() + .filter(|b| b.ident == assoc_item.ident) + .next() + .map(|bound| (bound, assoc_item))) + { + cause.span = bound.span; + cause.code = traits::AssocTypeBound(item_span, assoc_item.ident.span); + } + } + } + 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 diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 18b103960c7..b4b8d4566d5 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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); } diff --git a/src/test/ui/issues/issue-43784-associated-type.rs b/src/test/ui/issues/issue-43784-associated-type.rs index fb58ad6600f..92083d88f1b 100644 --- a/src/test/ui/issues/issue-43784-associated-type.rs +++ b/src/test/ui/issues/issue-43784-associated-type.rs @@ -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() {} diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index e91e53499ce..cfab66302cd 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -1,10 +1,17 @@ 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 | impl<T> Complete for T { - | - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` +LL | type Assoc: Partial<Self>; + | ----- associated type defined here +... +LL | / impl<T> Complete for T { + | | - help: consider restricting this bound: `T: std::marker::Copy` +LL | | type Assoc = T; + | | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` +LL | | } + | |_- in this `impl` item + | + = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/traits/cycle-cache-err-60010.rs b/src/test/ui/traits/cycle-cache-err-60010.rs index 45aa1b3c522..cbddef082be 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.rs +++ b/src/test/ui/traits/cycle-cache-err-60010.rs @@ -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 diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr index 9192f7ba2e3..a7b8dd05527 100644 --- a/src/test/ui/traits/cycle-cache-err-60010.stderr +++ b/src/test/ui/traits/cycle-cache-err-60010.stderr @@ -7,10 +7,16 @@ 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 | impl Database for RootDatabase { - | ^^^^^^^^ +LL | type Storage; + | ------- associated type defined here +... +LL | / impl Database for RootDatabase { +LL | | type Storage = SalsaStorage; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | | } + | |_- in this `impl` item | = note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery` = note: required because it appears within the type `SalsaStorage` |
