about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs20
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs46
-rw-r--r--tests/ui/error-emitter/E0308-clarification.rs16
-rw-r--r--tests/ui/error-emitter/E0308-clarification.svg97
-rw-r--r--tests/ui/impl-trait/impl-trait-in-macro.stderr4
-rw-r--r--tests/ui/impl-trait/universal-two-impl-traits.stderr4
6 files changed, 160 insertions, 27 deletions
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 797dcd7b4d1..38b8ea22084 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -641,7 +641,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         found_label: &dyn fmt::Display,
         found: DiagStyledString,
     ) -> &mut Self {
-        self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"")
+        self.note_expected_found_extra(
+            expected_label,
+            expected,
+            found_label,
+            found,
+            DiagStyledString::normal(""),
+            DiagStyledString::normal(""),
+        )
     }
 
     #[rustc_lint_diagnostics]
@@ -651,8 +658,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         expected: DiagStyledString,
         found_label: &dyn fmt::Display,
         found: DiagStyledString,
-        expected_extra: &dyn fmt::Display,
-        found_extra: &dyn fmt::Display,
+        expected_extra: DiagStyledString,
+        found_extra: DiagStyledString,
     ) -> &mut Self {
         let expected_label = expected_label.to_string();
         let expected_label = if expected_label.is_empty() {
@@ -677,10 +684,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
             expected_label
         ))];
         msg.extend(expected.0);
-        msg.push(StringPart::normal(format!("`{expected_extra}\n")));
+        msg.push(StringPart::normal(format!("`")));
+        msg.extend(expected_extra.0);
+        msg.push(StringPart::normal(format!("\n")));
         msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label)));
         msg.extend(found.0);
-        msg.push(StringPart::normal(format!("`{found_extra}")));
+        msg.push(StringPart::normal(format!("`")));
+        msg.extend(found_extra.0);
 
         // For now, just attach these as notes.
         self.highlighted_note(msg);
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 db4a14356cc..75700fbc4c2 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1725,32 +1725,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     }
                 }
                 TypeError::Sorts(values) => {
-                    let extra = expected == found;
+                    let extra = expected == found
+                        // Ensure that we don't ever say something like
+                        // expected `impl Trait` (opaque type `impl Trait`)
+                        //    found `impl Trait` (opaque type `impl Trait`)
+                        && values.expected.sort_string(self.tcx)
+                            != values.found.sort_string(self.tcx);
                     let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
                         (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
                             let sm = self.tcx.sess.source_map();
                             let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
-                            format!(
+                            DiagStyledString::normal(format!(
                                 " (opaque type at <{}:{}:{}>)",
                                 sm.filename_for_diagnostics(&pos.file.name),
                                 pos.line,
                                 pos.col.to_usize() + 1,
-                            )
+                            ))
                         }
                         (true, ty::Alias(ty::Projection, proj))
                             if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
                         {
                             let sm = self.tcx.sess.source_map();
                             let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
-                            format!(
+                            DiagStyledString::normal(format!(
                                 " (trait associated opaque type at <{}:{}:{}>)",
                                 sm.filename_for_diagnostics(&pos.file.name),
                                 pos.line,
                                 pos.col.to_usize() + 1,
-                            )
+                            ))
                         }
-                        (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
-                        (false, _) => "".to_string(),
+                        (true, _) => {
+                            let mut s = DiagStyledString::normal(" (");
+                            s.push_highlighted(ty.sort_string(self.tcx));
+                            s.push_normal(")");
+                            s
+                        }
+                        (false, _) => DiagStyledString::normal(""),
                     };
                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
                         || (exp_found.is_some_and(|ef| {
@@ -1767,23 +1777,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             }
                         }))
                     {
-                        if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
+                        if let Some(ExpectedFound { found: found_ty, .. }) = exp_found
+                            && !self.tcx.ty_is_opaque_future(found_ty)
+                        {
                             // `Future` is a special opaque type that the compiler
                             // will try to hide in some case such as `async fn`, so
                             // to make an error more use friendly we will
                             // avoid to suggest a mismatch type with a
                             // type that the user usually are not using
                             // directly such as `impl Future<Output = u8>`.
-                            if !self.tcx.ty_is_opaque_future(found_ty) {
-                                diag.note_expected_found_extra(
-                                    &expected_label,
-                                    expected,
-                                    &found_label,
-                                    found,
-                                    &sort_string(values.expected),
-                                    &sort_string(values.found),
-                                );
-                            }
+                            diag.note_expected_found_extra(
+                                &expected_label,
+                                expected,
+                                &found_label,
+                                found,
+                                sort_string(values.expected),
+                                sort_string(values.found),
+                            );
                         }
                     }
                 }
diff --git a/tests/ui/error-emitter/E0308-clarification.rs b/tests/ui/error-emitter/E0308-clarification.rs
new file mode 100644
index 00000000000..4c15ede0041
--- /dev/null
+++ b/tests/ui/error-emitter/E0308-clarification.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Zunstable-options --error-format=human-unicode --color=always
+//@ only-linux
+// Ensure that when we have a type error where both types have the same textual representation, the
+// diagnostic machinery highlights the clarifying comment that comes after in parentheses.
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+fn main() {
+    let mut x = (hide(0_u32), hide(0_i32));
+    x = (x.1, x.0);
+}
diff --git a/tests/ui/error-emitter/E0308-clarification.svg b/tests/ui/error-emitter/E0308-clarification.svg
new file mode 100644
index 00000000000..9432e3a4ee9
--- /dev/null
+++ b/tests/ui/error-emitter/E0308-clarification.svg
@@ -0,0 +1,97 @@
+<svg width="740px" height="668px" xmlns="http://www.w3.org/2000/svg">
+  <style>
+    .fg { fill: #AAAAAA }
+    .bg { background: #000000 }
+    .fg-ansi256-009 { fill: #FF5555 }
+    .fg-ansi256-012 { fill: #5555FF }
+    .fg-magenta { fill: #AA00AA }
+    .container {
+      padding: 0 10px;
+      line-height: 18px;
+    }
+    .bold { font-weight: bold; }
+    tspan {
+      font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+      white-space: pre;
+      line-height: 18px;
+    }
+  </style>
+
+  <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
+
+  <text xml:space="preserve" class="container fg">
+    <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: mismatched types</tspan>
+</tspan>
+    <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/E0308-clarification.rs:15:10</tspan>
+</tspan>
+    <tspan x="10px" y="64px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+</tspan>
+    <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> fn hide&lt;T: Foo&gt;(x: T) -&gt; impl Foo {</tspan>
+</tspan>
+    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">┬───────</tspan>
+</tspan>
+    <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><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>                          </tspan><tspan class="fg-ansi256-012 bold">the expected opaque type</tspan>
+</tspan>
+    <tspan x="10px" y="154px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">the found opaque type</tspan>
+</tspan>
+    <tspan x="10px" y="172px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan>
+</tspan>
+    <tspan x="10px" y="190px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>     x = (x.1, x.0);</tspan>
+</tspan>
+    <tspan x="10px" y="208px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>          </tspan><tspan class="fg-ansi256-009 bold">━━━</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `u32`, found `i32`</tspan>
+</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 class="bold">note</tspan><tspan>: expected opaque type `</tspan><tspan class="fg-magenta bold">impl Foo</tspan><tspan>` (</tspan><tspan class="fg-magenta bold">`u32`</tspan><tspan>)</tspan>
+</tspan>
+    <tspan x="10px" y="262px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>          found opaque type `</tspan><tspan class="fg-magenta bold">impl Foo</tspan><tspan>` (</tspan><tspan class="fg-magenta bold">`i32`</tspan><tspan>)</tspan>
+</tspan>
+    <tspan x="10px" y="280px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰ </tspan><tspan class="bold">note</tspan><tspan>: distinct uses of `impl Trait` result in different opaque types</tspan>
+</tspan>
+    <tspan x="10px" y="298px">
+</tspan>
+    <tspan x="10px" y="316px"><tspan class="fg-ansi256-009 bold">error[E0308]</tspan><tspan class="bold">: mismatched types</tspan>
+</tspan>
+    <tspan x="10px" y="334px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold"> ╭▸ </tspan><tspan>$DIR/E0308-clarification.rs:15:15</tspan>
+</tspan>
+    <tspan x="10px" y="352px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+</tspan>
+    <tspan x="10px" y="370px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan> fn hide&lt;T: Foo&gt;(x: T) -&gt; impl Foo {</tspan>
+</tspan>
+    <tspan x="10px" y="388px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">┬───────</tspan>
+</tspan>
+    <tspan x="10px" y="406px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+</tspan>
+    <tspan x="10px" y="424px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">the expected opaque type</tspan>
+</tspan>
+    <tspan x="10px" y="442px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>                          </tspan><tspan class="fg-ansi256-012 bold">the found opaque type</tspan>
+</tspan>
+    <tspan x="10px" y="460px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">‡</tspan>
+</tspan>
+    <tspan x="10px" y="478px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>     x = (x.1, x.0);</tspan>
+</tspan>
+    <tspan x="10px" y="496px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>               </tspan><tspan class="fg-ansi256-009 bold">━━━</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">expected `i32`, found `u32`</tspan>
+</tspan>
+    <tspan x="10px" y="514px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan>
+</tspan>
+    <tspan x="10px" y="532px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">├ </tspan><tspan class="bold">note</tspan><tspan>: expected opaque type `</tspan><tspan class="fg-magenta bold">impl Foo</tspan><tspan>` (</tspan><tspan class="fg-magenta bold">`i32`</tspan><tspan>)</tspan>
+</tspan>
+    <tspan x="10px" y="550px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">│</tspan><tspan>          found opaque type `</tspan><tspan class="fg-magenta bold">impl Foo</tspan><tspan>` (</tspan><tspan class="fg-magenta bold">`u32`</tspan><tspan>)</tspan>
+</tspan>
+    <tspan x="10px" y="568px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">╰ </tspan><tspan class="bold">note</tspan><tspan>: distinct uses of `impl Trait` result in different opaque types</tspan>
+</tspan>
+    <tspan x="10px" y="586px">
+</tspan>
+    <tspan x="10px" y="604px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 2 previous errors</tspan>
+</tspan>
+    <tspan x="10px" y="622px">
+</tspan>
+    <tspan x="10px" y="640px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
+</tspan>
+    <tspan x="10px" y="658px">
+</tspan>
+  </text>
+
+</svg>
diff --git a/tests/ui/impl-trait/impl-trait-in-macro.stderr b/tests/ui/impl-trait/impl-trait-in-macro.stderr
index 4380f47c5de..2f934694f83 100644
--- a/tests/ui/impl-trait/impl-trait-in-macro.stderr
+++ b/tests/ui/impl-trait/impl-trait-in-macro.stderr
@@ -12,8 +12,8 @@ LL |     let mut a = x;
 LL |     a = y;
    |         ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
    |
-   = note: expected type parameter `impl Debug` (type parameter `impl Debug`)
-              found type parameter `impl Debug` (type parameter `impl Debug`)
+   = note: expected type parameter `impl Debug`
+              found type parameter `impl Debug`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
 
diff --git a/tests/ui/impl-trait/universal-two-impl-traits.stderr b/tests/ui/impl-trait/universal-two-impl-traits.stderr
index 3b4844ab133..f2f5dd0a0c8 100644
--- a/tests/ui/impl-trait/universal-two-impl-traits.stderr
+++ b/tests/ui/impl-trait/universal-two-impl-traits.stderr
@@ -10,8 +10,8 @@ LL |     let mut a = x;
 LL |     a = y;
    |         ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug`
    |
-   = note: expected type parameter `impl Debug` (type parameter `impl Debug`)
-              found type parameter `impl Debug` (type parameter `impl Debug`)
+   = note: expected type parameter `impl Debug`
+              found type parameter `impl Debug`
    = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
    = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters