about summary refs log tree commit diff
diff options
context:
space:
mode:
author许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com>2024-10-28 13:36:18 +0800
committerGitHub <noreply@github.com>2024-10-28 13:36:18 +0800
commit20d2a546fad1f33b017ba6f43028dbeca6be923b (patch)
treecc771af945c66e0e2c23e709e17b15cb6ed32088
parent95a9d496f3f552af7e3bc8ddeb11137f98357e4b (diff)
parent5980a32ef1b8a542bbf64e685af09d5a87d9b501 (diff)
downloadrust-20d2a546fad1f33b017ba6f43028dbeca6be923b.tar.gz
rust-20d2a546fad1f33b017ba6f43028dbeca6be923b.zip
Rollup merge of #132086 - estebank:long-types, r=jieyouxu
Tweak E0277 highlighting and "long type" path printing

Partially address #132013.

![Output from this PR for the repro case in #132013](https://github.com/user-attachments/assets/a073ba37-4adc-411e-81f7-6cb9a945ce3d)
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs28
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs11
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs38
-rw-r--r--tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs20
-rw-r--r--tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg62
6 files changed, 145 insertions, 25 deletions
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 b7e2ed391cd..6014ed555b6 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
@@ -1835,6 +1835,7 @@ 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 `{}` ",
@@ -1842,16 +1843,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         )),
                         StringPart::highlighted("is"),
                         StringPart::normal(" implemented for `"),
-                        StringPart::highlighted(impl_trait_ref.self_ty().to_string()),
+                        if let [TypeError::Sorts(_)] = &terrs[..] {
+                            StringPart::normal(self_ty)
+                        } else {
+                            StringPart::highlighted(self_ty)
+                        },
                         StringPart::normal("`"),
                     ]);
 
                     if let [TypeError::Sorts(exp_found)] = &terrs[..] {
                         let exp_found = self.resolve_vars_if_possible(*exp_found);
-                        err.help(format!(
-                            "for that trait implementation, expected `{}`, found `{}`",
-                            exp_found.expected, exp_found.found
-                        ));
+                        err.highlighted_help(vec![
+                            StringPart::normal("for that trait implementation, "),
+                            StringPart::normal("expected `"),
+                            StringPart::highlighted(exp_found.expected.to_string()),
+                            StringPart::normal("`, found `"),
+                            StringPart::highlighted(exp_found.found.to_string()),
+                            StringPart::normal("`"),
+                        ]);
                     }
 
                     true
@@ -2160,6 +2169,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // First, attempt to add note to this error with an async-await-specific
         // message, and fall back to regular note otherwise.
         if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            let mut long_ty_file = None;
             self.note_obligation_cause_code(
                 obligation.cause.body_id,
                 err,
@@ -2168,7 +2178,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 obligation.cause.code(),
                 &mut vec![],
                 &mut Default::default(),
+                &mut long_ty_file,
             );
+            if let Some(file) = long_ty_file {
+                err.note(format!(
+                    "the full name for the type has been written to '{}'",
+                    file.display(),
+                ));
+                err.note("consider using `--verbose` to print the full type name to the console");
+            }
             self.suggest_unsized_bound_if_applicable(err, obligation);
             if let Some(span) = err.span.primary_span()
                 && let Some(mut diag) =
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index ca23f776581..b108a9352a5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -305,6 +305,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 if let ObligationCauseCode::WhereClause(..)
                 | ObligationCauseCode::WhereClauseInExpr(..) = code
                 {
+                    let mut long_ty_file = None;
                     self.note_obligation_cause_code(
                         error.obligation.cause.body_id,
                         &mut diag,
@@ -313,7 +314,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         code,
                         &mut vec![],
                         &mut Default::default(),
+                        &mut long_ty_file,
                     );
+                    if let Some(file) = long_ty_file {
+                        diag.note(format!(
+                            "the full name for the type has been written to '{}'",
+                            file.display(),
+                        ));
+                        diag.note(
+                            "consider using `--verbose` to print the full type name to the console",
+                        );
+                    }
                 }
                 diag.emit()
             }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
index f4c5733d4a6..c47c2169691 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs
@@ -144,6 +144,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             obligation.cause.span,
             suggest_increasing_limit,
             |err| {
+                let mut long_ty_file = None;
                 self.note_obligation_cause_code(
                     obligation.cause.body_id,
                     err,
@@ -152,7 +153,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     obligation.cause.code(),
                     &mut vec![],
                     &mut Default::default(),
+                    &mut long_ty_file,
                 );
+                if let Some(file) = long_ty_file {
+                    err.note(format!(
+                        "the full name for the type has been written to '{}'",
+                        file.display(),
+                    ));
+                    err.note(
+                        "consider using `--verbose` to print the full type name to the console",
+                    );
+                }
             },
         );
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 1fe93cb017a..a7d1f1bd8d0 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3,6 +3,7 @@
 use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
+use std::path::PathBuf;
 
 use itertools::{EitherOrBoth, Itertools};
 use rustc_data_structures::fx::FxHashSet;
@@ -2703,6 +2704,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         // Add a note for the item obligation that remains - normally a note pointing to the
         // bound that introduced the obligation (e.g. `T: Send`).
         debug!(?next_code);
+        let mut long_ty_file = None;
         self.note_obligation_cause_code(
             obligation.cause.body_id,
             err,
@@ -2711,6 +2713,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             next_code.unwrap(),
             &mut Vec::new(),
             &mut Default::default(),
+            &mut long_ty_file,
         );
     }
 
@@ -2723,11 +2726,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         cause_code: &ObligationCauseCode<'tcx>,
         obligated_types: &mut Vec<Ty<'tcx>>,
         seen_requirements: &mut FxHashSet<DefId>,
+        long_ty_file: &mut Option<PathBuf>,
     ) where
         T: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>,
     {
-        let mut long_ty_file = None;
-
         let tcx = self.tcx;
         let predicate = predicate.upcast(tcx);
         let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| {
@@ -2957,9 +2959,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
             ObligationCauseCode::Coercion { source, target } => {
                 let source =
-                    tcx.short_ty_string(self.resolve_vars_if_possible(source), &mut long_ty_file);
+                    tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file);
                 let target =
-                    tcx.short_ty_string(self.resolve_vars_if_possible(target), &mut long_ty_file);
+                    tcx.short_ty_string(self.resolve_vars_if_possible(target), long_ty_file);
                 err.note(with_forced_trimmed_paths!(format!(
                     "required for the cast from `{source}` to `{target}`",
                 )));
@@ -3249,7 +3251,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 };
 
                 if !is_upvar_tys_infer_tuple {
-                    let ty_str = tcx.short_ty_string(ty, &mut long_ty_file);
+                    let ty_str = tcx.short_ty_string(ty, long_ty_file);
                     let msg = format!("required because it appears within the type `{ty_str}`");
                     match ty.kind() {
                         ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
@@ -3327,6 +3329,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             &data.parent_code,
                             obligated_types,
                             seen_requirements,
+                            long_ty_file,
                         )
                     });
                 } else {
@@ -3339,6 +3342,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             cause_code.peel_derives(),
                             obligated_types,
                             seen_requirements,
+                            long_ty_file,
                         )
                     });
                 }
@@ -3347,8 +3351,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let mut parent_trait_pred =
                     self.resolve_vars_if_possible(data.derived.parent_trait_pred);
                 let parent_def_id = parent_trait_pred.def_id();
-                let self_ty_str = tcx
-                    .short_ty_string(parent_trait_pred.skip_binder().self_ty(), &mut long_ty_file);
+                let self_ty_str =
+                    tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
                 let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
                 let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
                 let mut is_auto_trait = false;
@@ -3444,10 +3448,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         count,
                         pluralize!(count)
                     ));
-                    let self_ty = tcx.short_ty_string(
-                        parent_trait_pred.skip_binder().self_ty(),
-                        &mut long_ty_file,
-                    );
+                    let self_ty = tcx
+                        .short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file);
                     err.note(format!(
                         "required for `{self_ty}` to implement `{}`",
                         parent_trait_pred.print_modifiers_and_trait_path()
@@ -3463,6 +3465,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         &data.parent_code,
                         obligated_types,
                         seen_requirements,
+                        long_ty_file,
                     )
                 });
             }
@@ -3479,6 +3482,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         &data.parent_code,
                         obligated_types,
                         seen_requirements,
+                        long_ty_file,
                     )
                 });
             }
@@ -3493,6 +3497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         nested,
                         obligated_types,
                         seen_requirements,
+                        long_ty_file,
                     )
                 });
                 let mut multispan = MultiSpan::from(span);
@@ -3523,6 +3528,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         parent_code,
                         obligated_types,
                         seen_requirements,
+                        long_ty_file,
                     )
                 });
             }
@@ -3562,7 +3568,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
             ObligationCauseCode::OpaqueReturnType(expr_info) => {
                 if let Some((expr_ty, hir_id)) = expr_info {
-                    let expr_ty = self.tcx.short_ty_string(expr_ty, &mut long_ty_file);
+                    let expr_ty = self.tcx.short_ty_string(expr_ty, long_ty_file);
                     let expr = self.infcx.tcx.hir().expect_expr(hir_id);
                     err.span_label(
                         expr.span,
@@ -3574,14 +3580,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
             }
         }
-
-        if let Some(file) = long_ty_file {
-            err.note(format!(
-                "the full name for the type has been written to '{}'",
-                file.display(),
-            ));
-            err.note("consider using `--verbose` to print the full type name to the console");
-        }
     }
 
     #[instrument(
diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs
new file mode 100644
index 00000000000..f1c196a154d
--- /dev/null
+++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.rs
@@ -0,0 +1,20 @@
+//@ only-linux
+//@ compile-flags: --error-format=human --color=always
+//@ error-pattern: the trait bound
+
+trait Foo<T>: Bar<T> {}
+
+trait Bar<T> {}
+
+struct Struct;
+
+impl<T, K> Foo<K> for T where T: Bar<K>
+{}
+
+impl<'a> Bar<()> for Struct {}
+
+fn foo() -> impl Foo<i32> {
+    Struct
+}
+
+fn main() {}
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
new file mode 100644
index 00000000000..e09b96e5ff2
--- /dev/null
+++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
@@ -0,0 +1,62 @@
+<svg width="1104px" height="344px" xmlns="http://www.w3.org/2000/svg">
+  <style>
+    .fg { fill: #AAAAAA }
+    .bg { background: #000000 }
+    .fg-ansi256-009 { fill: #FF5555 }
+    .fg-ansi256-010 { fill: #55FF55 }
+    .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[E0277]</tspan><tspan class="bold">: the trait bound `Struct: Foo&lt;i32&gt;` is not satisfied</tspan>
+</tspan>
+    <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/highlight-difference-between-expected-trait-and-found-trait.rs:16:13</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 foo() -&gt; impl Foo&lt;i32&gt; {</tspan>
+</tspan>
+    <tspan x="10px" y="100px"><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">the trait `Bar&lt;i32&gt;` is not implemented for `Struct`, which is required by `Struct: Foo&lt;i32&gt;`</tspan>
+</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>
+    <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>
+    <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>
+    <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>
+    <tspan x="10px" y="208px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</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>
+    <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>
+    <tspan x="10px" y="262px">
+</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>
+    <tspan x="10px" y="298px">
+</tspan>
+    <tspan x="10px" y="316px"><tspan class="bold">For more information about this error, try `rustc --explain E0277`.</tspan>
+</tspan>
+    <tspan x="10px" y="334px">
+</tspan>
+  </text>
+
+</svg>