about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-10-24 22:16:43 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-11-02 03:08:04 +0000
commitb7fc1a743122e3c45f105a5d1169a042a2c6e8bf (patch)
tree1e26a4fee38823f1ba577c5aae2109643c955136
parent7c7bb7dc017545db732f5cffec684bbaeae0a9a0 (diff)
downloadrust-b7fc1a743122e3c45f105a5d1169a042a2c6e8bf.tar.gz
rust-b7fc1a743122e3c45f105a5d1169a042a2c6e8bf.zip
Add trait diff highlighting logic and use it in E0277
When a trait is not implemented for a type, but there *is* an `impl`
for another type or different trait params, we format the output to
use highlighting in the same way that E0308 does for types.

The logic accounts for 3 cases:
- When both the type and trait in the expected predicate and the candidate are different
- When only the types are different
- When only the trait generic params are different

For each case, we use slightly different formatting and wording.
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs61
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs68
-rw-r--r--tests/ui/const-generics/associated-type-bound-fail.stderr3
-rw-r--r--tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr6
-rw-r--r--tests/ui/const-generics/defaults/trait_objects_fail.stderr6
-rw-r--r--tests/ui/const-generics/defaults/wfness.stderr6
-rw-r--r--tests/ui/const-generics/occurs-check/unused-substs-1.stderr3
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr3
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr3
-rw-r--r--tests/ui/generic-const-items/unsatisfied-bounds.stderr6
-rw-r--r--tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg28
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-62742.stderr6
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.stderr6
-rw-r--r--tests/ui/indexing/index-help.stderr3
-rw-r--r--tests/ui/indexing/indexing-requires-a-uint.stderr3
-rw-r--r--tests/ui/indexing/point-at-index-for-obligation-failure.stderr3
-rw-r--r--tests/ui/integral-indexing.stderr24
-rw-r--r--tests/ui/issues/issue-34334.stderr3
-rw-r--r--tests/ui/issues/issue-45801.stderr3
-rw-r--r--tests/ui/issues/issue-66923-show-error-for-correct-call.stderr6
-rw-r--r--tests/ui/iterators/invalid-iterator-chain-fixable.stderr6
-rw-r--r--tests/ui/iterators/invalid-iterator-chain.stderr6
-rw-r--r--tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr3
-rw-r--r--tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr3
-rw-r--r--tests/ui/on-unimplemented/impl-substs.stderr3
-rw-r--r--tests/ui/on-unimplemented/on-impl.stderr6
-rw-r--r--tests/ui/on-unimplemented/slice-index.stderr3
-rw-r--r--tests/ui/str/str-idx.stderr9
-rw-r--r--tests/ui/str/str-mut-idx.stderr9
-rw-r--r--tests/ui/suggestions/issue-101623.stderr3
-rw-r--r--tests/ui/suggestions/suggest-dereferencing-index.stderr3
-rw-r--r--tests/ui/traits/coercion-generic-bad.stderr3
-rw-r--r--tests/ui/traits/negative-bounds/simple.stderr3
-rw-r--r--tests/ui/try-block/try-block-bad-type.stderr3
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr3
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr3
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.current.stderr3
-rw-r--r--tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr3
40 files changed, 251 insertions, 86 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 574cf1e88b1..4725047090e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -766,6 +766,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         values
     }
 
+    pub fn cmp_traits(
+        &self,
+        def_id1: DefId,
+        args1: &[ty::GenericArg<'tcx>],
+        def_id2: DefId,
+        args2: &[ty::GenericArg<'tcx>],
+    ) -> (DiagStyledString, DiagStyledString) {
+        let mut values = (DiagStyledString::new(), DiagStyledString::new());
+
+        if def_id1 != def_id2 {
+            values.0.push_highlighted(self.tcx.def_path_str(def_id1).as_str());
+            values.1.push_highlighted(self.tcx.def_path_str(def_id2).as_str());
+        } else {
+            values.0.push_normal(self.tcx.item_name(def_id1).as_str());
+            values.1.push_normal(self.tcx.item_name(def_id2).as_str());
+        }
+
+        if args1.len() != args2.len() {
+            let (pre, post) = if args1.len() > 0 { ("<", ">") } else { ("", "") };
+            values.0.push_normal(format!(
+                "{pre}{}{post}",
+                args1.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
+            ));
+            let (pre, post) = if args2.len() > 0 { ("<", ">") } else { ("", "") };
+            values.1.push_normal(format!(
+                "{pre}{}{post}",
+                args2.iter().map(|a| a.to_string()).collect::<Vec<_>>().join(", ")
+            ));
+            return values;
+        }
+
+        if args1.len() > 0 {
+            values.0.push_normal("<");
+            values.1.push_normal("<");
+        }
+        for (i, (a, b)) in std::iter::zip(args1, args2).enumerate() {
+            let a_str = a.to_string();
+            let b_str = b.to_string();
+            if let (Some(a), Some(b)) = (a.as_type(), b.as_type()) {
+                let (a, b) = self.cmp(a, b);
+                values.0.0.extend(a.0);
+                values.1.0.extend(b.0);
+            } else if a_str != b_str {
+                values.0.push_highlighted(a_str);
+                values.1.push_highlighted(b_str);
+            } else {
+                values.0.push_normal(a_str);
+                values.1.push_normal(b_str);
+            }
+            if i + 1 < args1.len() {
+                values.0.push_normal(", ");
+                values.1.push_normal(", ");
+            }
+        }
+        if args1.len() > 0 {
+            values.0.push_normal(">");
+            values.1.push_normal(">");
+        }
+        values
+    }
+
     /// Compares two given types, eliding parts that are the same between them and highlighting
     /// relevant differences, and return two representation of those types for highlighted printing.
     pub fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagStyledString, DiagStyledString) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 7aa558cfd3f..358c244eca9 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1832,21 +1832,63 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     if impl_trait_ref.references_error() {
                         return false;
                     }
-                    let self_ty = impl_trait_ref.self_ty().to_string();
-                    err.highlighted_help(vec![
-                        StringPart::normal(format!(
-                            "the trait `{}` ",
-                            impl_trait_ref.print_trait_sugared()
-                        )),
-                        StringPart::highlighted("is"),
+
+                    let traits = self.cmp_traits(
+                        obligation_trait_ref.def_id,
+                        &obligation_trait_ref.args[1..],
+                        impl_trait_ref.def_id,
+                        &impl_trait_ref.args[1..],
+                    );
+                    let traits_content = (traits.0.content(), traits.1.content());
+                    let types = self.cmp(obligation_trait_ref.self_ty(), impl_trait_ref.self_ty());
+                    let types_content = (types.0.content(), types.1.content());
+                    let mut msg = vec![StringPart::normal("the trait `")];
+                    if traits_content.0 == traits_content.1 {
+                        msg.push(StringPart::normal(
+                            impl_trait_ref.print_trait_sugared().to_string(),
+                        ));
+                    } else {
+                        msg.extend(traits.0.0);
+                    }
+                    msg.extend([
+                        StringPart::normal("` "),
+                        StringPart::highlighted("is not"),
                         StringPart::normal(" implemented for `"),
-                        if let [TypeError::Sorts(_)] = &terrs[..] {
-                            StringPart::normal(self_ty)
-                        } else {
-                            StringPart::highlighted(self_ty)
-                        },
-                        StringPart::normal("`"),
                     ]);
+                    if types_content.0 == types_content.1 {
+                        msg.push(StringPart::normal(obligation_trait_ref.self_ty().to_string()));
+                    } else {
+                        msg.extend(types.0.0);
+                    }
+                    msg.push(StringPart::normal("`"));
+                    if types_content.0 == types_content.1 {
+                        msg.push(StringPart::normal("\nbut trait `"));
+                        msg.extend(traits.1.0);
+                        msg.extend([
+                            StringPart::normal("` "),
+                            StringPart::highlighted("is"),
+                            StringPart::normal(" implemented for it"),
+                        ]);
+                    } else if traits_content.0 == traits_content.1 {
+                        msg.extend([
+                            StringPart::normal("\nbut it "),
+                            StringPart::highlighted("is"),
+                            StringPart::normal(" implemented for `"),
+                        ]);
+                        msg.extend(types.1.0);
+                        msg.push(StringPart::normal("`"));
+                    } else {
+                        msg.push(StringPart::normal("\nbut trait `"));
+                        msg.extend(traits.1.0);
+                        msg.extend([
+                            StringPart::normal("` "),
+                            StringPart::highlighted("is"),
+                            StringPart::normal(" implemented for `"),
+                        ]);
+                        msg.extend(types.1.0);
+                        msg.push(StringPart::normal("`"));
+                    }
+                    err.highlighted_help(msg);
 
                     if let [TypeError::Sorts(exp_found)] = &terrs[..] {
                         let exp_found = self.resolve_vars_if_possible(*exp_found);
diff --git a/tests/ui/const-generics/associated-type-bound-fail.stderr b/tests/ui/const-generics/associated-type-bound-fail.stderr
index 602a8927a85..e92aad7cec3 100644
--- a/tests/ui/const-generics/associated-type-bound-fail.stderr
+++ b/tests/ui/const-generics/associated-type-bound-fail.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
 LL |     type Assoc = u16;
    |                  ^^^ the trait `Bar<N>` is not implemented for `u16`
    |
-   = help: the trait `Bar<3>` is implemented for `u16`
+   = help: the trait `Bar<N>` is not implemented for `u16`
+           but trait `Bar<3>` is implemented for it
 note: required by a bound in `Foo::Assoc`
   --> $DIR/associated-type-bound-fail.rs:4:17
    |
diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr
index 45be3126e3b..e36f645b263 100644
--- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr
+++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr
@@ -18,7 +18,8 @@ LL |
 LL |     1_u32
    |     ----- return type was inferred to be `u32` here
    |
-   = help: the trait `Traitor<N, 2>` is implemented for `u32`
+   = help: the trait `Traitor<N, N>` is not implemented for `u32`
+           but trait `Traitor<N, 2>` is implemented for it
 
 error[E0277]: the trait bound `u64: Traitor` is not satisfied
   --> $DIR/rp_impl_trait_fail.rs:21:13
@@ -29,7 +30,8 @@ LL |
 LL |     1_u64
    |     ----- return type was inferred to be `u64` here
    |
-   = help: the trait `Traitor<1, 2>` is implemented for `u64`
+   = help: the trait `Traitor<1, 1>` is not implemented for `u64`
+           but trait `Traitor<1, 2>` is implemented for it
 
 error[E0284]: type annotations needed
   --> $DIR/rp_impl_trait_fail.rs:28:5
diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.stderr b/tests/ui/const-generics/defaults/trait_objects_fail.stderr
index 481d77728b9..2390dfeadb9 100644
--- a/tests/ui/const-generics/defaults/trait_objects_fail.stderr
+++ b/tests/ui/const-generics/defaults/trait_objects_fail.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied
 LL |     foo(&10_u32);
    |         ^^^^^^^ the trait `Trait` is not implemented for `u32`
    |
-   = help: the trait `Trait<2>` is implemented for `u32`
+   = help: the trait `Trait<12>` is not implemented for `u32`
+           but trait `Trait<2>` is implemented for it
    = note: required for the cast from `&u32` to `&dyn Trait`
 
 error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
@@ -13,7 +14,8 @@ error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
 LL |     bar(&true);
    |         ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
    |
-   = help: the trait `Traitor<2, 3>` is implemented for `bool`
+   = help: the trait `Traitor<_, _>` is not implemented for `bool`
+           but trait `Traitor<2, 3>` is implemented for it
    = note: required for the cast from `&bool` to `&dyn Traitor<_>`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr
index bd9bfcd7dad..290a80bd32f 100644
--- a/tests/ui/const-generics/defaults/wfness.stderr
+++ b/tests/ui/const-generics/defaults/wfness.stderr
@@ -10,7 +10,8 @@ error[E0277]: the trait bound `(): Trait<2>` is not satisfied
 LL |     (): Trait<N>;
    |         ^^^^^^^^ the trait `Trait<2>` is not implemented for `()`
    |
-   = help: the trait `Trait<3>` is implemented for `()`
+   = help: the trait `Trait<2>` is not implemented for `()`
+           but trait `Trait<3>` is implemented for it
 
 error[E0277]: the trait bound `(): Trait<1>` is not satisfied
   --> $DIR/wfness.rs:18:13
@@ -18,7 +19,8 @@ error[E0277]: the trait bound `(): Trait<1>` is not satisfied
 LL | fn foo() -> DependentDefaultWfness {
    |             ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()`
    |
-   = help: the trait `Trait<3>` is implemented for `()`
+   = help: the trait `Trait<1>` is not implemented for `()`
+           but trait `Trait<3>` is implemented for it
 note: required by a bound in `WhereClause`
   --> $DIR/wfness.rs:8:9
    |
diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
index 0184a059327..07e86aa17f2 100644
--- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
+++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied
 LL |     let _ = A;
    |             ^ the trait `Bar<_>` is not implemented for `A<_>`
    |
-   = help: the trait `Bar<_>` is implemented for `A<{ 6 + 1 }>`
+   = help: the trait `Bar<_>` is not implemented for `A<_>`
+           but it is implemented for `A<{ 6 + 1 }>`
 note: required by a bound in `A`
   --> $DIR/unused-substs-1.rs:9:11
    |
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
index 41f222e46a7..5d0c1826411 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
 LL |     SelectInt.check("bar");
    |               ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
    |
-   = help: the trait `AsExpression<Text>` is implemented for `&str`
+   = help: the trait `AsExpression<Integer>` is not implemented for `&str`
+           but trait `AsExpression<Text>` is implemented for it
    = help: for that trait implementation, expected `Text`, found `Integer`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
index 8c01b61191e..1e1eae852f9 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -22,7 +22,8 @@ error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
 LL |     SelectInt.check("bar");
    |               ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
    |
-   = help: the trait `AsExpression<Text>` is implemented for `&str`
+   = help: the trait `AsExpression<Integer>` is not implemented for `&str`
+           but trait `AsExpression<Text>` is implemented for it
    = help: for that trait implementation, expected `Text`, found `Integer`
 
 error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
index 14894cef770..de252b816e5 100644
--- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr
+++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr
@@ -16,7 +16,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
 LL |     let () = K::<()>;
    |                  ^^ the trait `From<()>` is not implemented for `Infallible`
    |
-   = help: the trait `From<!>` is implemented for `Infallible`
+   = help: the trait `From<()>` is not implemented for `Infallible`
+           but trait `From<!>` is implemented for it
    = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `K`
   --> $DIR/unsatisfied-bounds.rs:12:17
@@ -48,7 +49,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied
 LL |     let _ = <() as Trait<&'static str>>::B::<()>;
    |                                              ^^ the trait `From<()>` is not implemented for `Infallible`
    |
-   = help: the trait `From<!>` is implemented for `Infallible`
+   = help: the trait `From<()>` is not implemented for `Infallible`
+           but trait `From<!>` is implemented for it
    = help: for that trait implementation, expected `!`, found `()`
 note: required by a bound in `Trait::B`
   --> $DIR/unsatisfied-bounds.rs:21:21
diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
index a18fc11a1e3..277fd1536bc 100644
--- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
+++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
@@ -1,4 +1,4 @@
-<svg width="1104px" height="344px" xmlns="http://www.w3.org/2000/svg">
+<svg width="1104px" height="362px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
     .bg { background: #000000 }
@@ -33,29 +33,31 @@
 </tspan>
     <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Bar&lt;()&gt;` </tspan><tspan class="fg-magenta bold">is</tspan><tspan> implemented for `Struct`</tspan>
+    <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Bar&lt;</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>&gt;` </tspan><tspan class="fg-magenta bold">is not</tspan><tspan> implemented for `Struct`</tspan>
 </tspan>
-    <tspan x="10px" y="154px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: for that trait implementation, expected `</tspan><tspan class="fg-magenta bold">()</tspan><tspan>`, found `</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>`</tspan>
+    <tspan x="10px" y="154px"><tspan>           but trait `Bar&lt;</tspan><tspan class="fg-magenta bold">()</tspan><tspan>&gt;` </tspan><tspan class="fg-magenta bold">is</tspan><tspan> implemented for it</tspan>
 </tspan>
-    <tspan x="10px" y="172px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required for `Struct` to implement `Foo&lt;i32&gt;`</tspan>
+    <tspan x="10px" y="172px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: for that trait implementation, expected `</tspan><tspan class="fg-magenta bold">()</tspan><tspan>`, found `</tspan><tspan class="fg-magenta bold">i32</tspan><tspan>`</tspan>
 </tspan>
-    <tspan x="10px" y="190px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/highlight-difference-between-expected-trait-and-found-trait.rs:11:12</tspan>
+    <tspan x="10px" y="190px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required for `Struct` to implement `Foo&lt;i32&gt;`</tspan>
 </tspan>
-    <tspan x="10px" y="208px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+    <tspan x="10px" y="208px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/highlight-difference-between-expected-trait-and-found-trait.rs:11:12</tspan>
 </tspan>
-    <tspan x="10px" y="226px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> impl&lt;T, K&gt; Foo&lt;K&gt; for T where T: Bar&lt;K&gt;</tspan>
+    <tspan x="10px" y="226px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
 </tspan>
-    <tspan x="10px" y="244px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>            </tspan><tspan class="fg-ansi256-010 bold">^^^^^^</tspan><tspan>     </tspan><tspan class="fg-ansi256-010 bold">^</tspan><tspan>          </tspan><tspan class="fg-ansi256-012 bold">------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">unsatisfied trait bound introduced here</tspan>
+    <tspan x="10px" y="244px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> impl&lt;T, K&gt; Foo&lt;K&gt; for T where T: Bar&lt;K&gt;</tspan>
 </tspan>
-    <tspan x="10px" y="262px">
+    <tspan x="10px" y="262px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>            </tspan><tspan class="fg-ansi256-010 bold">^^^^^^</tspan><tspan>     </tspan><tspan class="fg-ansi256-010 bold">^</tspan><tspan>          </tspan><tspan class="fg-ansi256-012 bold">------</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">unsatisfied trait bound introduced here</tspan>
 </tspan>
-    <tspan x="10px" y="280px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
+    <tspan x="10px" y="280px">
 </tspan>
-    <tspan x="10px" y="298px">
+    <tspan x="10px" y="298px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
 </tspan>
-    <tspan x="10px" y="316px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
+    <tspan x="10px" y="316px">
 </tspan>
-    <tspan x="10px" y="334px">
+    <tspan x="10px" y="334px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
+</tspan>
+    <tspan x="10px" y="352px">
 </tspan>
   </text>
 
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
index 768224e4c51..663c9a7f2ae 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -32,7 +32,8 @@ LL |     fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
 LL |         self
    |         ---- return type was inferred to be `Bar` here
    |
-   = help: the trait `Foo<char>` is implemented for `Bar`
+   = help: the trait `Foo<u8>` is not implemented for `Bar`
+           but trait `Foo<char>` is implemented for it
    = help: for that trait implementation, expected `char`, found `u8`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr
index 94822e41ccd..98d17b02536 100644
--- a/tests/ui/impl-trait/issues/issue-62742.stderr
+++ b/tests/ui/impl-trait/issues/issue-62742.stderr
@@ -29,7 +29,8 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
 LL |     WrongImpl::foo(0i32);
    |     ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
    |
-   = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
+   = help: the trait `Raw<_>` is not implemented for `RawImpl<_>`
+           but trait `Raw<[_]>` is implemented for it
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:33:35
    |
@@ -67,7 +68,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
 LL |     WrongImpl::<()>::foo(0i32);
    |     ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
    |
-   = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
+   = help: the trait `Raw<()>` is not implemented for `RawImpl<()>`
+           but trait `Raw<[()]>` is implemented for it
    = help: for that trait implementation, expected `[()]`, found `()`
 note: required by a bound in `SafeImpl`
   --> $DIR/issue-62742.rs:33:35
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
index d98de650d0d..2e95ef370c7 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -83,7 +83,8 @@ error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied
 LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {}
    |                                                                               ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()`
    |
-   = help: the trait `Qux<'_>` is implemented for `()`
+   = help: the trait `Qux<'b>` is not implemented for `&'a ()`
+           but trait `Qux<'_>` is implemented for `()`
    = help: for that trait implementation, expected `()`, found `&'a ()`
 
 error: implementation of `Bar` is not general enough
@@ -101,7 +102,8 @@ error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied
 LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {}
    |                                                                ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()`
    |
-   = help: the trait `Qux<'_>` is implemented for `()`
+   = help: the trait `Qux<'b>` is not implemented for `&'a ()`
+           but trait `Qux<'_>` is implemented for `()`
    = help: for that trait implementation, expected `()`, found `&'a ()`
 
 error: aborting due to 9 previous errors
diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr
index 4ec28ddf871..d4637da1426 100644
--- a/tests/ui/indexing/index-help.stderr
+++ b/tests/ui/indexing/index-help.stderr
@@ -5,7 +5,8 @@ LL |     x[0i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr
index 3041c2c99a1..fdcf9b030a5 100644
--- a/tests/ui/indexing/indexing-requires-a-uint.stderr
+++ b/tests/ui/indexing/indexing-requires-a-uint.stderr
@@ -5,7 +5,8 @@ LL |     [0][0u8];
    |         ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[{integer}]` to implement `Index<u8>`
    = note: 1 redundant requirement hidden
diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
index 4cced22789f..0752231356c 100644
--- a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
+++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied
 LL |         &s
    |         ^^ the trait `Borrow<&str>` is not implemented for `String`
    |
-   = help: the trait `Borrow<str>` is implemented for `String`
+   = help: the trait `Borrow<&_>` is not implemented for `String`
+           but trait `Borrow<_>` is implemented for it
    = help: for that trait implementation, expected `str`, found `&str`
    = note: required for `HashMap<String, String>` to implement `Index<&&str>`
 
diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr
index 97e658617cf..f731d303774 100644
--- a/tests/ui/integral-indexing.stderr
+++ b/tests/ui/integral-indexing.stderr
@@ -5,7 +5,8 @@ LL |     v[3u8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `Vec<isize>` to implement `Index<u8>`
 
@@ -16,7 +17,8 @@ LL |     v[3i8];
    |       ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `Vec<isize>` to implement `Index<i8>`
 
@@ -27,7 +29,8 @@ LL |     v[3u32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `Vec<isize>` to implement `Index<u32>`
 
@@ -38,7 +41,8 @@ LL |     v[3i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[isize]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `Vec<isize>` to implement `Index<i32>`
 
@@ -49,7 +53,8 @@ LL |     s.as_bytes()[3u8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
-   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u8`
    = note: required for `[u8]` to implement `Index<u8>`
 
@@ -60,7 +65,8 @@ LL |     s.as_bytes()[3i8];
    |                  ^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
-   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i8`
    = note: required for `[u8]` to implement `Index<i8>`
 
@@ -71,7 +77,8 @@ LL |     s.as_bytes()[3u32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
-   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `u32`
    = note: required for `[u8]` to implement `Index<u32>`
 
@@ -82,7 +89,8 @@ LL |     s.as_bytes()[3i32];
    |                  ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[u8]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[u8]` to implement `Index<i32>`
 
diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr
index e14629f5f3a..8213136faa1 100644
--- a/tests/ui/issues/issue-34334.stderr
+++ b/tests/ui/issues/issue-34334.stderr
@@ -18,7 +18,8 @@ LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece
    |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
-   = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>`
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
+           but trait `FromIterator<(u32, _, _)>` is implemented for it
    = help: for that trait implementation, expected `(u32, _, _)`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-34334.rs:5:43
diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr
index 5a10c429564..940c1865fa3 100644
--- a/tests/ui/issues/issue-45801.stderr
+++ b/tests/ui/issues/issue-45801.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `Params: Plugin<i32>` is not satisfied
 LL |     req.get_ref::<Params>();
    |         ^^^^^^^ the trait `Plugin<i32>` is not implemented for `Params`
    |
-   = help: the trait `Plugin<Foo>` is implemented for `Params`
+   = help: the trait `Plugin<i32>` is not implemented for `Params`
+           but trait `Plugin<Foo>` is implemented for it
    = help: for that trait implementation, expected `Foo`, found `i32`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
index 128288e28f5..e62be48edf6 100644
--- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -5,7 +5,8 @@ LL |     let x2: Vec<f64> = x1.into_iter().collect();
    |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: the trait `FromIterator<&_>` is not implemented for `Vec<f64>`
+           but trait `FromIterator<_>` is implemented for it
    = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27
@@ -26,7 +27,8 @@ LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
    |                             required by a bound introduced by this call
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
-   = help: the trait `FromIterator<f64>` is implemented for `Vec<f64>`
+   = help: the trait `FromIterator<&_>` is not implemented for `Vec<f64>`
+           but trait `FromIterator<_>` is implemented for it
    = help: for that trait implementation, expected `f64`, found `&f64`
 note: the method call chain might not have had the expected associated types
   --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17
diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
index 3d3bbab8819..d6f82741c4c 100644
--- a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr
@@ -7,7 +7,8 @@ LL |     i.collect()
    |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
    |
    = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
-   = help: the trait `FromIterator<X>` is implemented for `Vec<X>`
+   = help: the trait `FromIterator<&_>` is not implemented for `Vec<X>`
+           but trait `FromIterator<_>` is implemented for it
    = help: for that trait implementation, expected `X`, found `&X`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-fixable.rs:5:26
@@ -124,7 +125,8 @@ LL |     let g: Vec<i32> = f.collect();
    |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
-   = help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+           but trait `FromIterator<i32>` is implemented for it
    = help: for that trait implementation, expected `i32`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain-fixable.rs:32:15
diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr
index bc35fcd489d..2522471b3b5 100644
--- a/tests/ui/iterators/invalid-iterator-chain.stderr
+++ b/tests/ui/iterators/invalid-iterator-chain.stderr
@@ -7,7 +7,8 @@ LL |     i.collect()
    |       ^^^^^^^ value of type `Vec<X>` cannot be built from `std::iter::Iterator<Item=&X>`
    |
    = help: the trait `FromIterator<&X>` is not implemented for `Vec<X>`
-   = help: the trait `FromIterator<X>` is implemented for `Vec<X>`
+   = help: the trait `FromIterator<&_>` is not implemented for `Vec<X>`
+           but trait `FromIterator<_>` is implemented for it
    = help: for that trait implementation, expected `X`, found `&X`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:4:26
@@ -181,7 +182,8 @@ LL |     let g: Vec<i32> = f.collect();
    |                         ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
-   = help: the trait `FromIterator<i32>` is implemented for `Vec<i32>`
+   = help: the trait `FromIterator<()>` is not implemented for `Vec<i32>`
+           but trait `FromIterator<i32>` is implemented for it
    = help: for that trait implementation, expected `i32`, found `()`
 note: the method call chain might not have had the expected associated types
   --> $DIR/invalid-iterator-chain.rs:44:15
diff --git a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr b/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr
index 3b8913ccf45..9eacab9a0b7 100644
--- a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr
+++ b/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied
 LL |     <E as From<_>>::from(never); // Should the inference fail?
    |      ^ the trait `From<()>` is not implemented for `E`
    |
-   = help: the trait `From<!>` is implemented for `E`
+   = help: the trait `From<()>` is not implemented for `E`
+           but trait `From<!>` is implemented for it
    = help: for that trait implementation, expected `!`, found `()`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
index f5249814c78..d6234c8e7e1 100644
--- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
+++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied
 LL |     <E as From<_>>::from(never);
    |      ^ the trait `From<()>` is not implemented for `E`
    |
-   = help: the trait `From<!>` is implemented for `E`
+   = help: the trait `From<()>` is not implemented for `E`
+           but trait `From<!>` is implemented for it
    = help: for that trait implementation, expected `!`, found `()`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr
index e2ba2474d6c..cdb9172ef0f 100644
--- a/tests/ui/on-unimplemented/impl-substs.stderr
+++ b/tests/ui/on-unimplemented/impl-substs.stderr
@@ -7,7 +7,8 @@ LL |     Foo::<usize>::foo((1i32, 1i32, 1i32));
    |     required by a bound introduced by this call
    |
    = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
-   = help: the trait `Foo<i32>` is implemented for `(i32, i32, i32)`
+   = help: the trait `Foo<usize>` is not implemented for `(i32, i32, i32)`
+           but trait `Foo<i32>` is implemented for it
    = help: for that trait implementation, expected `i32`, found `usize`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr
index c7d2a78af6c..d20b559def7 100644
--- a/tests/ui/on-unimplemented/on-impl.stderr
+++ b/tests/ui/on-unimplemented/on-impl.stderr
@@ -7,7 +7,8 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |     required by a bound introduced by this call
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+           but trait `Index<usize>` is implemented for it
    = help: for that trait implementation, expected `usize`, found `u32`
 
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
@@ -17,7 +18,8 @@ LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
-   = help: the trait `Index<usize>` is implemented for `[i32]`
+   = help: the trait `Index<u32>` is not implemented for `[i32]`
+           but trait `Index<usize>` is implemented for it
    = help: for that trait implementation, expected `usize`, found `u32`
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr
index d53ecb9db0c..8f7169b30d4 100644
--- a/tests/ui/on-unimplemented/slice-index.stderr
+++ b/tests/ui/on-unimplemented/slice-index.stderr
@@ -5,7 +5,8 @@ LL |     x[1i32];
    |       ^^^^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
-   = help: the trait `SliceIndex<[i32]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
+           but it is implemented for `usize`
    = help: for that trait implementation, expected `usize`, found `i32`
    = note: required for `[i32]` to implement `Index<i32>`
 
diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr
index e8bbb8058fa..0ce0c207561 100644
--- a/tests/ui/str/str-idx.stderr
+++ b/tests/ui/str/str-idx.stderr
@@ -7,7 +7,8 @@ LL |     let _: u8 = s[4];
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
+           but trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<{integer}>`
 
@@ -22,7 +23,8 @@ LL |     let _ = s.get(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
+           but trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
@@ -38,7 +40,8 @@ LL |     let _ = s.get_unchecked(4);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
+           but trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr
index 9390d689252..7bc46ff33b3 100644
--- a/tests/ui/str/str-mut-idx.stderr
+++ b/tests/ui/str/str-mut-idx.stderr
@@ -31,7 +31,8 @@ LL |     s[1usize] = bot();
    |       ^^^^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `usize`
+           but trait `SliceIndex<[_]>` is implemented for it
    = help: for that trait implementation, expected `[_]`, found `str`
    = note: required for `str` to implement `Index<usize>`
 
@@ -46,7 +47,8 @@ LL |     s.get_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
+           but trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
@@ -62,7 +64,8 @@ LL |     s.get_unchecked_mut(1);
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
-   = help: the trait `SliceIndex<[_]>` is implemented for `usize`
+   = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
+           but trait `SliceIndex<[_]>` is implemented for `usize`
    = help: for that trait implementation, expected `[_]`, found `str`
 note: required by a bound in `core::str::<impl str>::get_unchecked_mut`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr
index 4de91a1b995..0733e67ea02 100644
--- a/tests/ui/suggestions/issue-101623.stderr
+++ b/tests/ui/suggestions/issue-101623.stderr
@@ -7,7 +7,8 @@ LL |     Trait::do_stuff({ fun(&mut *inner) });
    |     |               the trait `Trait<'_>` is not implemented for `*mut ()`
    |     required by a bound introduced by this call
    |
-   = help: the trait `Trait<'_>` is implemented for `()`
+   = help: the trait `Trait<'_>` is not implemented for `*mut ()`
+           but it is implemented for `()`
    = help: for that trait implementation, expected `()`, found `*mut ()`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr
index 2316acbe9da..cd5364fcffb 100644
--- a/tests/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr
@@ -5,7 +5,8 @@ LL |     let one_item_please: i32 = [1, 2, 3][i];
    |                                          ^ slice indices are of type `usize` or ranges of `usize`
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
-   = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize`
+   = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_`
+           but it is implemented for `_`
    = help: for that trait implementation, expected `usize`, found `&usize`
    = note: required for `[{integer}]` to implement `Index<&usize>`
    = note: 1 redundant requirement hidden
diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr
index 26136c6f72c..c0553ea62c5 100644
--- a/tests/ui/traits/coercion-generic-bad.stderr
+++ b/tests/ui/traits/coercion-generic-bad.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `Struct: Trait<isize>` is not satisfied
 LL |     let s: Box<dyn Trait<isize>> = Box::new(Struct { person: "Fred" });
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<isize>` is not implemented for `Struct`
    |
-   = help: the trait `Trait<&'static str>` is implemented for `Struct`
+   = help: the trait `Trait<isize>` is not implemented for `Struct`
+           but trait `Trait<&'static str>` is implemented for it
    = help: for that trait implementation, expected `&'static str`, found `isize`
    = note: required for the cast from `Box<Struct>` to `Box<dyn Trait<isize>>`
 
diff --git a/tests/ui/traits/negative-bounds/simple.stderr b/tests/ui/traits/negative-bounds/simple.stderr
index b8d12138794..f8a43e605c4 100644
--- a/tests/ui/traits/negative-bounds/simple.stderr
+++ b/tests/ui/traits/negative-bounds/simple.stderr
@@ -28,7 +28,8 @@ error[E0277]: the trait bound `Copyable: !Copy` is not satisfied
 LL |     not_copy::<Copyable>();
    |                ^^^^^^^^ the trait bound `Copyable: !Copy` is not satisfied
    |
-   = help: the trait `Copy` is implemented for `Copyable`
+   = help: the trait `Copy` is not implemented for `Copyable`
+           but trait `Copy` is implemented for it
 note: required by a bound in `not_copy`
   --> $DIR/simple.rs:3:16
    |
diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr
index d94962e4031..c67ad762a83 100644
--- a/tests/ui/try-block/try-block-bad-type.stderr
+++ b/tests/ui/try-block/try-block-bad-type.stderr
@@ -7,7 +7,8 @@ LL |         Err("")?;
    |         this can't be annotated with `?` because it has type `Result<_, &str>`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = help: the trait `From<Infallible>` is implemented for `TryFromSliceError`
+   = help: the trait `From<&str>` is not implemented for `TryFromSliceError`
+           but trait `From<Infallible>` is implemented for it
    = help: for that trait implementation, expected `Infallible`, found `&str`
    = note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
 
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index fe28912ba00..20fe2d721bc 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -67,7 +67,8 @@ LL |     ControlFlow::Continue(Err("hello")?)
    |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
    |
    = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
-   = help: the trait `FromResidual<ControlFlow<String, Infallible>>` is implemented for `ControlFlow<String>`
+   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
+           but trait `FromResidual<ControlFlow<String, Infallible>>` is implemented for it
    = help: for that trait implementation, expected `ControlFlow<String, Infallible>`, found `Result<Infallible, &str>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
@@ -79,7 +80,8 @@ LL |     Some(3)?;
    |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
    |
    = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
-   = help: the trait `FromResidual<ControlFlow<u64, Infallible>>` is implemented for `ControlFlow<u64>`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
+           but trait `FromResidual<ControlFlow<u64, Infallible>>` is implemented for it
    = help: for that trait implementation, expected `ControlFlow<u64, Infallible>`, found `Option<Infallible>`
 
 error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
@@ -92,7 +94,8 @@ LL |     ControlFlow::Break(4_u8)?;
    |
    = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
    = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
-   = help: the trait `FromResidual<ControlFlow<i64, Infallible>>` is implemented for `ControlFlow<i64>`
+   = help: the trait `FromResidual<ControlFlow<u8, _>>` is not implemented for `ControlFlow<i64>`
+           but trait `FromResidual<ControlFlow<i64, _>>` is implemented for it
    = help: for that trait implementation, expected `i64`, found `u8`
 
 error: aborting due to 8 previous errors
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
index c215d197db4..d96c86a2e6f 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |              ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
    |
-   = help: the trait `Trait<()>` is implemented for `Foo`
+   = help: the trait `Trait<Bar>` is not implemented for `Foo`
+           but trait `Trait<()>` is implemented for it
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
index 34532afcbba..915432bbe67 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
@@ -7,7 +7,8 @@ LL | fn foo() -> impl Foo<FooX> {
 LL |     ()
    |     -- return type was inferred to be `()` here
    |
-   = help: the trait `Foo<()>` is implemented for `()`
+   = help: the trait `Foo<FooX>` is not implemented for `()`
+           but trait `Foo<()>` is implemented for it
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
index 3ae3590ca7f..1e799f15635 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
@@ -7,7 +7,8 @@ LL |     42_i32
    |     ------ return type was inferred to be `i32` here
    |
    = help: the trait `PartialEq<Foo>` is not implemented for `i32`
-   = help: the trait `PartialEq` is implemented for `i32`
+   = help: the trait `PartialEq<Foo>` is not implemented for `i32`
+           but trait `PartialEq<i32>` is implemented for it
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
index ab307aadec9..5c0d98735f7 100644
--- a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
+++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr
@@ -4,7 +4,8 @@ error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
 LL |     let _: Bar = ((),).into();
    |                        ^^^^ the trait `Foo<'_>` is not implemented for `((),)`
    |
-   = help: the trait `Foo<'_>` is implemented for `()`
+   = help: the trait `Foo<'_>` is not implemented for `((),)`
+           but it is implemented for `()`
    = help: for that trait implementation, expected `()`, found `((),)`
 note: required for `Bar` to implement `From<((),)>`
   --> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22