about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-01-29 18:31:02 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-01-30 21:28:18 +0000
commit6efddac288643c4b0bc85ea317ea275e6cb4739f (patch)
tree2a8729a40eb6266fc410458c64066fa3ffa40c94 /compiler/rustc_trait_selection
parentf3d71c9249072413f014b378bb5ea79c8a7dc9a7 (diff)
downloadrust-6efddac288643c4b0bc85ea317ea275e6cb4739f.tar.gz
rust-6efddac288643c4b0bc85ea317ea275e6cb4739f.zip
Provide more context on derived obligation error primary label
Expand the primary span of E0277 when the immediate unmet bound is not what the user wrote:

```
error[E0277]: the trait bound `i32: Bar` is not satisfied
 --> f100.rs:6:6
  |
6 |     <i32 as Foo>::foo();
  |      ^^^ the trait `Bar` is not implemented for `i32`, which is required by `i32: Foo`
  |
help: this trait has no implementations, consider adding one
 --> f100.rs:2:1
  |
2 | trait Bar {}
  | ^^^^^^^^^
note: required for `i32` to implement `Foo`
 --> f100.rs:3:14
  |
3 | impl<T: Bar> Foo for T {}
  |         ---  ^^^     ^
  |         |
  |         unsatisfied trait bound introduced here
```

Fix #40120.
Diffstat (limited to 'compiler/rustc_trait_selection')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs41
1 files changed, 25 insertions, 16 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 69649e36178..5bab57ca56c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1432,20 +1432,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     ) -> bool {
         let span = obligation.cause.span;
 
-        let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
-            obligation.cause.code()
-        {
-            parent_code
-        } else if let ObligationCauseCode::ItemObligation(_)
-        | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
-        {
-            obligation.cause.code()
-        } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
-            span.ctxt().outer_expn_data().kind
-        {
-            obligation.cause.code()
-        } else {
-            return false;
+        let code = match obligation.cause.code() {
+            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => parent_code,
+            c @ ObligationCauseCode::ItemObligation(_)
+            | c @ ObligationCauseCode::ExprItemObligation(..) => c,
+            c if matches!(
+                span.ctxt().outer_expn_data().kind,
+                ExpnKind::Desugaring(DesugaringKind::ForLoop)
+            ) =>
+            {
+                c
+            }
+            _ => return false,
         };
 
         // List of traits for which it would be nonsensical to suggest borrowing.
@@ -4978,16 +4976,27 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             _ => None,
         };
 
+        let pred = obligation.predicate;
+        let (_, base) = obligation.cause.code().peel_derives_with_predicate();
+        let post = if let ty::PredicateKind::Clause(clause) = pred.kind().skip_binder()
+            && let ty::ClauseKind::Trait(pred) = clause
+            && let Some(base) = base
+            && base.skip_binder() != pred
+        {
+            format!(", which is required by `{base}`")
+        } else {
+            String::new()
+        };
         match ty_desc {
             Some(desc) => format!(
-                "{}the trait `{}` is not implemented for {} `{}`",
+                "{}the trait `{}` is not implemented for {} `{}`{post}",
                 pre_message,
                 trait_predicate.print_modifiers_and_trait_path(),
                 desc,
                 tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),
             ),
             None => format!(
-                "{}the trait `{}` is not implemented for `{}`",
+                "{}the trait `{}` is not implemented for `{}`{post}",
                 pre_message,
                 trait_predicate.print_modifiers_and_trait_path(),
                 tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),