about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-10-27 03:34:54 +0000
committerbors <bors@rust-lang.org>2019-10-27 03:34:54 +0000
commitcf148a717a275741a35b5f51eab182aa42bd06a6 (patch)
treeb97e5b9189f938fe34a367a6d3d9a06caad964cc
parentfcf516d827300d21eb9f6312e799578b6f359d5d (diff)
parent3a4cacd45891db4a898606fc7b26d4b73009e5c3 (diff)
downloadrust-cf148a717a275741a35b5f51eab182aa42bd06a6.tar.gz
rust-cf148a717a275741a35b5f51eab182aa42bd06a6.zip
Auto merge of #65288 - estebank:point-at-assoc-type, r=nikomatsakis
Point at associated type for some obligations

Partially address #57663.
-rw-r--r--src/librustc/traits/error_reporting.rs52
-rw-r--r--src/librustc/traits/mod.rs2
-rw-r--r--src/librustc/traits/structural_impls.rs1
-rw-r--r--src/librustc/ty/mod.rs1
-rw-r--r--src/librustc/ty/wf.rs172
-rw-r--r--src/librustc_typeck/check/wfcheck.rs23
-rw-r--r--src/test/compile-fail/chalkify/impl_wf.rs1
-rw-r--r--src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs11
-rw-r--r--src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr14
-rw-r--r--src/test/ui/associated-types/point-at-type-on-obligation-failure.rs20
-rw-r--r--src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr17
-rw-r--r--src/test/ui/issues/issue-43784-associated-type.rs4
-rw-r--r--src/test/ui/issues/issue-43784-associated-type.stderr14
-rw-r--r--src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs2
-rw-r--r--src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr18
-rw-r--r--src/test/ui/traits/cycle-cache-err-60010.rs4
-rw-r--r--src/test/ui/traits/cycle-cache-err-60010.stderr9
17 files changed, 304 insertions, 61 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index e684cdc0a38..be9e24cb1a2 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -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");
+                }
+            }
         }
     }
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index eb4b114eb30..1a1c021c3ea 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -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.
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 18db3c8d10b..ca80bb66cb7 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -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)),
         }
     }
 }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4660e8025d4..ca01992f2d0 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -3141,6 +3141,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 b50e819c956..4ea01bf9647 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,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
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/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs
index 96b1b253371..6bb4cf86e79 100644
--- a/src/test/compile-fail/chalkify/impl_wf.rs
+++ b/src/test/compile-fail/chalkify/impl_wf.rs
@@ -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 { }
diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs
new file mode 100644
index 00000000000..9360d96f05e
--- /dev/null
+++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs
@@ -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() {}
diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
new file mode 100644
index 00000000000..f1a2e343a7e
--- /dev/null
+++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
@@ -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`.
diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs
new file mode 100644
index 00000000000..dc43dbaf54b
--- /dev/null
+++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.rs
@@ -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() {}
diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr
new file mode 100644
index 00000000000..e4bd39c8ba6
--- /dev/null
+++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure.stderr
@@ -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`.
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..393b012f5f8 100644
--- a/src/test/ui/issues/issue-43784-associated-type.stderr
+++ b/src/test/ui/issues/issue-43784-associated-type.stderr
@@ -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
 
diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs
index 265ccb3125c..394512c5794 100644
--- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs
+++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs
@@ -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() {}
diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr
index bdea8ab97e5..c6f2e5cda66 100644
--- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr
+++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr
@@ -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`
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..f439de88261 100644
--- a/src/test/ui/traits/cycle-cache-err-60010.stderr
+++ b/src/test/ui/traits/cycle-cache-err-60010.stderr
@@ -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`