about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorNadrieril <Nadrieril@users.noreply.github.com>2024-01-31 12:10:51 +0100
committerGitHub <noreply@github.com>2024-01-31 12:10:51 +0100
commit0313eb21826c8f99e055ba9909472e40c258df6d (patch)
tree5f8110074ba57ecfc974f3633395142a33b75225 /compiler/rustc_trait_selection/src
parenta7d5382e5c2a4cabca29667b246d9dfa6164ba85 (diff)
parent6efddac288643c4b0bc85ea317ea275e6cb4739f (diff)
downloadrust-0313eb21826c8f99e055ba9909472e40c258df6d.tar.gz
rust-0313eb21826c8f99e055ba9909472e40c258df6d.zip
Rollup merge of #120469 - estebank:issue-40120, r=TaKO8Ki
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/src')
-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),