Show more information when multiple impl
apply
This commit is contained in:
parent
79f38b7914
commit
2817ece19c
@ -17,6 +17,7 @@ use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
|
|||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||||
use crate::traits::specialize::to_pretty_impl_header;
|
use crate::traits::specialize::to_pretty_impl_header;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
|
use ambiguity::Ambiguity::*;
|
||||||
use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
|
use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
@ -2366,14 +2367,28 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ambiguities = ambiguity::recompute_applicable_impls(
|
let mut ambiguities = ambiguity::recompute_applicable_impls(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
&obligation.with(self.tcx, trait_ref),
|
&obligation.with(self.tcx, trait_ref),
|
||||||
);
|
);
|
||||||
let has_non_region_infer =
|
let has_non_region_infer =
|
||||||
trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
|
trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
|
||||||
// It doesn't make sense to talk about applicable impls if there are more
|
// It doesn't make sense to talk about applicable impls if there are more than a
|
||||||
// than a handful of them.
|
// handful of them. If there are a lot of them, but only a few of them have no type
|
||||||
|
// params, we only show those, as they are more likely to be useful/intended.
|
||||||
|
if ambiguities.len() > 20 {
|
||||||
|
let infcx = self.infcx;
|
||||||
|
if !ambiguities.iter().all(|option| match option {
|
||||||
|
DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
|
||||||
|
ParamEnv(_) => true,
|
||||||
|
}) {
|
||||||
|
// If not all are blanket impls, we filter blanked impls out.
|
||||||
|
ambiguities.retain(|option| match option {
|
||||||
|
DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
|
||||||
|
ParamEnv(_) => true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
|
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
|
||||||
if self.tainted_by_errors().is_some() && subst.is_none() {
|
if self.tainted_by_errors().is_some() && subst.is_none() {
|
||||||
// If `subst.is_none()`, then this is probably two param-env
|
// If `subst.is_none()`, then this is probably two param-env
|
||||||
@ -2392,7 +2407,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
err.note(format!("cannot satisfy `{predicate}`"));
|
err.note(format!("cannot satisfy `{predicate}`"));
|
||||||
let impl_candidates = self
|
let impl_candidates = self
|
||||||
.find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
|
.find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
|
||||||
if impl_candidates.len() < 10 {
|
if impl_candidates.len() < 40 {
|
||||||
self.report_similar_impl_candidates(
|
self.report_similar_impl_candidates(
|
||||||
impl_candidates.as_slice(),
|
impl_candidates.as_slice(),
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let x = "hello".chars().rev().collect();
|
let x = "hello".chars().rev().collect();
|
||||||
//~^ ERROR E0282
|
//~^ ERROR E0282
|
||||||
|
//~| ERROR E0283
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,39 @@ help: consider giving `x` an explicit type
|
|||||||
LL | let x: Vec<_> = "hello".chars().rev().collect();
|
LL | let x: Vec<_> = "hello".chars().rev().collect();
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0283]: type annotations needed
|
||||||
|
--> $DIR/E0282.rs:2:9
|
||||||
|
|
|
||||||
|
LL | let x = "hello".chars().rev().collect();
|
||||||
|
| ^ ------- type must be known at this point
|
||||||
|
|
|
||||||
|
= note: multiple `impl`s satisfying `_: FromIterator<char>` found in the following crates: `alloc`, `hashbrown`, `std`:
|
||||||
|
- impl FromIterator<char> for String;
|
||||||
|
- impl<'a, T> FromIterator<T> for Cow<'a, [T]>
|
||||||
|
where T: Clone;
|
||||||
|
- impl<'a> FromIterator<char> for Cow<'a, str>;
|
||||||
|
- impl<I> FromIterator<I> for Box<[I]>;
|
||||||
|
- impl<T, S, A> FromIterator<T> for hashbrown::set::HashSet<T, S, A>
|
||||||
|
where T: Eq, T: Hash, S: BuildHasher, S: Default, A: Default, A: Allocator, A: Clone;
|
||||||
|
- impl<T, S> FromIterator<T> for HashSet<T, S>
|
||||||
|
where T: Eq, T: Hash, S: BuildHasher, S: Default;
|
||||||
|
- impl<T> FromIterator<T> for Arc<[T]>;
|
||||||
|
- impl<T> FromIterator<T> for BTreeSet<T>
|
||||||
|
where T: Ord;
|
||||||
|
- impl<T> FromIterator<T> for BinaryHeap<T>
|
||||||
|
where T: Ord;
|
||||||
|
- impl<T> FromIterator<T> for LinkedList<T>;
|
||||||
|
- impl<T> FromIterator<T> for Rc<[T]>;
|
||||||
|
- impl<T> FromIterator<T> for Vec<T>;
|
||||||
|
- impl<T> FromIterator<T> for VecDeque<T>;
|
||||||
|
note: required by a bound in `collect`
|
||||||
|
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||||
|
help: consider giving `x` an explicit type
|
||||||
|
|
|
||||||
|
LL | let x: Vec<_> = "hello".chars().rev().collect();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0282`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0282, E0283.
|
||||||
|
For more information about an error, try `rustc --explain E0282`.
|
||||||
|
50
tests/ui/inference/multiple-impl-apply.rs
Normal file
50
tests/ui/inference/multiple-impl-apply.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
struct Foo {
|
||||||
|
inner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
inner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Baz {
|
||||||
|
inner: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Baz> for Bar {
|
||||||
|
fn from(other: Baz) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: other.inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Baz> for Foo {
|
||||||
|
fn from(other: Baz) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: other.inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: Baz = Baz { inner: 42 };
|
||||||
|
|
||||||
|
// DOESN'T Compile: Multiple options!
|
||||||
|
let y = x.into();
|
||||||
|
//~^ ERROR E0282
|
||||||
|
//~| ERROR E0283
|
||||||
|
|
||||||
|
let y_1: Foo = x.into();
|
||||||
|
let y_2: Bar = x.into();
|
||||||
|
|
||||||
|
let z_1 = Foo::from(y_1);
|
||||||
|
let z_2 = Bar::from(y_2);
|
||||||
|
|
||||||
|
// No type annotations needed, the compiler KNOWS the type must be `Foo`!
|
||||||
|
let m = magic_foo(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn magic_foo(arg: Baz) -> Foo {
|
||||||
|
arg.into()
|
||||||
|
}
|
35
tests/ui/inference/multiple-impl-apply.stderr
Normal file
35
tests/ui/inference/multiple-impl-apply.stderr
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/multiple-impl-apply.rs:34:9
|
||||||
|
|
|
||||||
|
LL | let y = x.into();
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
help: consider giving `y` an explicit type
|
||||||
|
|
|
||||||
|
LL | let y: /* Type */ = x.into();
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
|
error[E0283]: type annotations needed
|
||||||
|
--> $DIR/multiple-impl-apply.rs:34:9
|
||||||
|
|
|
||||||
|
LL | let y = x.into();
|
||||||
|
| ^ ---- type must be known at this point
|
||||||
|
|
|
||||||
|
note: multiple `impl`s satisfying `_: From<Baz>` found
|
||||||
|
--> $DIR/multiple-impl-apply.rs:14:1
|
||||||
|
|
|
||||||
|
LL | impl From<Baz> for Bar {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | impl From<Baz> for Foo {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: required for `Baz` to implement `Into<_>`
|
||||||
|
help: consider giving `y` an explicit type
|
||||||
|
|
|
||||||
|
LL | let y: /* Type */ = x.into();
|
||||||
|
| ++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0282, E0283.
|
||||||
|
For more information about an error, try `rustc --explain E0282`.
|
@ -9,6 +9,7 @@ fn g() -> Result<Vec<i32>, ()> {
|
|||||||
let l = [1, 2, 3, 4];
|
let l = [1, 2, 3, 4];
|
||||||
l.iter().map(f).collect()?
|
l.iter().map(f).collect()?
|
||||||
//~^ ERROR type annotations needed
|
//~^ ERROR type annotations needed
|
||||||
|
//~| ERROR type annotations needed
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -9,6 +9,21 @@ help: consider specifying the generic argument
|
|||||||
LL | l.iter().map(f).collect::<Vec<_>>()?
|
LL | l.iter().map(f).collect::<Vec<_>>()?
|
||||||
| ++++++++++
|
| ++++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0283]: type annotations needed
|
||||||
|
--> $DIR/question-mark-type-infer.rs:10:21
|
||||||
|
|
|
||||||
|
LL | l.iter().map(f).collect()?
|
||||||
|
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
|
||||||
|
|
|
||||||
|
= note: cannot satisfy `_: FromIterator<Result<i32, ()>>`
|
||||||
|
note: required by a bound in `collect`
|
||||||
|
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||||
|
help: consider specifying the generic argument
|
||||||
|
|
|
||||||
|
LL | l.iter().map(f).collect::<Vec<_>>()?
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0282`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0282, E0283.
|
||||||
|
For more information about an error, try `rustc --explain E0282`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user