1
Fork 0

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.
This commit is contained in:
Nadrieril 2024-01-31 12:10:51 +01:00 committed by GitHub
commit 0313eb2182
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
196 changed files with 382 additions and 373 deletions

View file

@ -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),