parent
3aac307ca6
commit
ac8cbbd200
8 changed files with 115 additions and 6 deletions
|
@ -2,10 +2,11 @@ pub mod on_unimplemented;
|
||||||
pub mod suggestions;
|
pub mod suggestions;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
|
DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError,
|
||||||
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
|
FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation,
|
||||||
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
|
ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
|
||||||
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
|
OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
|
||||||
|
TraitNotObjectSafe,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
||||||
|
@ -654,11 +655,77 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
} else if !suggested {
|
} else if !suggested {
|
||||||
// Can't show anything else useful, try to find similar impls.
|
// Can't show anything else useful, try to find similar impls.
|
||||||
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
|
||||||
self.report_similar_impl_candidates(
|
if !self.report_similar_impl_candidates(
|
||||||
impl_candidates,
|
impl_candidates,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
&mut err,
|
&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
|
// Changing mutability doesn't make a difference to whether we have
|
||||||
|
|
|
@ -6,6 +6,7 @@ LL | writes_to_specific_path(&cap);
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| 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`
|
note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
|
||||||
--> $DIR/issue-85848.rs:21:12
|
--> $DIR/issue-85848.rs:21:12
|
||||||
|
|
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ LL | Err("whoops")?;
|
||||||
| ^ the trait `From<&str>` is not implemented for `impl Debug`
|
| ^ 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
|
= 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>`
|
= 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
|
error[E0277]: the trait bound `impl Debug: From<&str>` is not satisfied
|
||||||
|
|
|
@ -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 }
|
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`
|
| ^^^^^^^^^^^^^^^^^^^^^ 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>`
|
= 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
|
error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
|
||||||
|
@ -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 }
|
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
|
| ^^^^^^^^^^^^^^^^^^^^^ 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>`
|
= note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
|
@ -7,6 +7,7 @@ LL | Err(5)?;
|
||||||
| ^ the trait `From<{integer}>` is not implemented for `()`
|
| ^ 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
|
= 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, ()>`
|
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -80,6 +80,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||||
LL | let a = t as Box<dyn Gettable<String>>;
|
LL | let a = t as Box<dyn Gettable<String>>;
|
||||||
| ^ the trait `Copy` is not implemented for `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>`
|
note: required because of the requirements on the impl of `Gettable<String>` for `S<String>`
|
||||||
--> $DIR/kindck-impl-type-params.rs:14:32
|
--> $DIR/kindck-impl-type-params.rs:14:32
|
||||||
|
|
|
|
||||||
|
@ -93,6 +94,7 @@ error[E0277]: the trait bound `Foo: Copy` is not satisfied
|
||||||
LL | let a: Box<dyn Gettable<Foo>> = t;
|
LL | let a: Box<dyn Gettable<Foo>> = t;
|
||||||
| ^ the trait `Copy` is not implemented for `Foo`
|
| ^ 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>`
|
note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>`
|
||||||
--> $DIR/kindck-impl-type-params.rs:14:32
|
--> $DIR/kindck-impl-type-params.rs:14:32
|
||||||
|
|
|
|
||||||
|
|
12
src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
Normal file
12
src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
Normal file
|
@ -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() {}
|
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue