Skip to content

Commit

Permalink
Fix rust-lang#90970, doesn't address rust-lang#87437
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Apr 4, 2022
1 parent 3aac307 commit ac8cbbd
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 6 deletions.
79 changes: 73 additions & 6 deletions compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ pub mod on_unimplemented;
pub mod suggestions;

use super::{
EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError,
FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation,
ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
TraitNotObjectSafe,
};

use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
Expand Down Expand Up @@ -654,11 +655,77 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} else if !suggested {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(
if !self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
&mut err,
);
) {
// This is *almost* equivalent to
// `obligation.cause.code().peel_derives()`, but it gives us the
// trait predicate for that corresponding root obligation. This
// lets us get a derived obligation from a type parameter, like
// when calling `string.strip_suffix(p)` where `p` is *not* an
// implementer of `Pattern<'_>`.
let mut code = obligation.cause.code();
let mut trait_pred = trait_predicate;
let mut peeled = false;
loop {
match &*code {
ObligationCauseCode::FunctionArgumentObligation {
parent_code,
..
} => {
code = &parent_code;
}
ObligationCauseCode::ImplDerivedObligation(
box ImplDerivedObligationCause {
derived:
DerivedObligationCause {
parent_code,
parent_trait_pred,
},
..
},
)
| ObligationCauseCode::BuiltinDerivedObligation(
DerivedObligationCause {
parent_code,
parent_trait_pred,
},
)
| ObligationCauseCode::DerivedObligation(
DerivedObligationCause {
parent_code,
parent_trait_pred,
},
) => {
peeled = true;
code = &parent_code;
trait_pred = *parent_trait_pred;
}
_ => break,
};
}
let def_id = trait_pred.def_id();
// Mention *all* the `impl`s for the *top most* obligation, the
// user might have meant to use one of them, if any found. We skip
// auto-traits or fundamental traits that might not be exactly what
// the user might expect to be presented with. Instead this is
// useful for less general traits.
if peeled
&& !self.tcx.trait_is_auto(def_id)
&& !self.tcx.lang_items().items().contains(&Some(def_id))
{
let trait_ref = trait_pred.to_poly_trait_ref();
let impl_candidates =
self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
&mut err,
);
}
}
}

// Changing mutability doesn't make a difference to whether we have
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | writes_to_specific_path(&cap);
| |
| required by a bound introduced by this call
|
= help: the trait `Delegates<U>` is implemented for `T`
note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
--> $DIR/issue-85848.rs:21:12
|
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/impl-trait/cross-return-site-inference.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ LL | Err("whoops")?;
| ^ the trait `From<&str>` is not implemented for `impl Debug`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<(), impl Debug>`

error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/impl-trait/nested_impl_trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfie
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
|
= help: the trait `Into<U>` is implemented for `T`
= note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`

error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
Expand All @@ -60,6 +61,7 @@ error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfie
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
|
= help: the trait `Into<U>` is implemented for `T`
= note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`

error: aborting due to 8 previous errors
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/issues/issue-32709.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ LL | Err(5)?;
| ^ the trait `From<{integer}>` is not implemented for `()`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`

error: aborting due to previous error
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/kindck/kindck-impl-type-params.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
LL | let a = t as Box<dyn Gettable<String>>;
| ^ the trait `Copy` is not implemented for `String`
|
= help: the trait `Gettable<T>` is implemented for `S<T>`
note: required because of the requirements on the impl of `Gettable<String>` for `S<String>`
--> $DIR/kindck-impl-type-params.rs:14:32
|
Expand All @@ -93,6 +94,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied
LL | let a: Box<dyn Gettable<Foo>> = t;
| ^ the trait `Copy` is not implemented for `Foo`
|
= help: the trait `Gettable<T>` is implemented for `S<T>`
note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>`
--> $DIR/kindck-impl-type-params.rs:14:32
|
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fn strip_lf(s: &str) -> &str {
s.strip_suffix(b'\n').unwrap_or(s)
//~^ ERROR expected a `FnMut<(char,)>` closure, found `u8`
//~| NOTE expected an `FnMut<(char,)>` closure, found `u8`
//~| NOTE required by a bound introduced by this call
//~| HELP the trait `FnMut<(char,)>` is not implemented for `u8`
//~| HELP the following other types implement trait `Pattern<'_>`:
//~| NOTE required because of the requirements on the impl of `Pattern<'_>` for `u8`

}

fn main() {}
23 changes: 23 additions & 0 deletions src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0277]: expected a `FnMut<(char,)>` closure, found `u8`
--> $DIR/assoc-fn-bound-root-obligation.rs:2:20
|
LL | s.strip_suffix(b'\n').unwrap_or(s)
| ------------ ^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
| |
| required by a bound introduced by this call
|
= help: the trait `FnMut<(char,)>` is not implemented for `u8`
= help: the following other types implement trait `Pattern<'_>`:
&'b String
&'b [char; N]
&'b [char]
&'b str
&'c &'b str
[char; N]
char
pattern::MultiCharEqPattern<C>
= note: required because of the requirements on the impl of `Pattern<'_>` for `u8`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit ac8cbbd

Please sign in to comment.