Skip to content

Commit 2817ece

Browse files
committed
Show more information when multiple impl apply
1 parent 79f38b7 commit 2817ece

File tree

7 files changed

+158
-8
lines changed

7 files changed

+158
-8
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::solve::{GenerateProofTree, InferCtxtEvalExt, UseGlobalCache};
1717
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
1818
use crate::traits::specialize::to_pretty_impl_header;
1919
use crate::traits::NormalizeExt;
20+
use ambiguity::Ambiguity::*;
2021
use on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _};
2122
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
2223
use rustc_errors::{
@@ -2366,14 +2367,28 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23662367
)
23672368
};
23682369

2369-
let ambiguities = ambiguity::recompute_applicable_impls(
2370+
let mut ambiguities = ambiguity::recompute_applicable_impls(
23702371
self.infcx,
23712372
&obligation.with(self.tcx, trait_ref),
23722373
);
23732374
let has_non_region_infer =
23742375
trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
2375-
// It doesn't make sense to talk about applicable impls if there are more
2376-
// than a handful of them.
2376+
// It doesn't make sense to talk about applicable impls if there are more than a
2377+
// handful of them. If there are a lot of them, but only a few of them have no type
2378+
// params, we only show those, as they are more likely to be useful/intended.
2379+
if ambiguities.len() > 20 {
2380+
let infcx = self.infcx;
2381+
if !ambiguities.iter().all(|option| match option {
2382+
DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
2383+
ParamEnv(_) => true,
2384+
}) {
2385+
// If not all are blanket impls, we filter blanked impls out.
2386+
ambiguities.retain(|option| match option {
2387+
DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(),
2388+
ParamEnv(_) => true,
2389+
});
2390+
}
2391+
}
23772392
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
23782393
if self.tainted_by_errors().is_some() && subst.is_none() {
23792394
// If `subst.is_none()`, then this is probably two param-env
@@ -2392,7 +2407,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
23922407
err.note(format!("cannot satisfy `{predicate}`"));
23932408
let impl_candidates = self
23942409
.find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
2395-
if impl_candidates.len() < 10 {
2410+
if impl_candidates.len() < 40 {
23962411
self.report_similar_impl_candidates(
23972412
impl_candidates.as_slice(),
23982413
trait_ref,

tests/ui/error-codes/E0282.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
fn main() {
22
let x = "hello".chars().rev().collect();
33
//~^ ERROR E0282
4+
//~| ERROR E0283
45
}

tests/ui/error-codes/E0282.stderr

+35-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,39 @@ help: consider giving `x` an explicit type
99
LL | let x: Vec<_> = "hello".chars().rev().collect();
1010
| ++++++++
1111

12-
error: aborting due to previous error
12+
error[E0283]: type annotations needed
13+
--> $DIR/E0282.rs:2:9
14+
|
15+
LL | let x = "hello".chars().rev().collect();
16+
| ^ ------- type must be known at this point
17+
|
18+
= note: multiple `impl`s satisfying `_: FromIterator<char>` found in the following crates: `alloc`, `hashbrown`, `std`:
19+
- impl FromIterator<char> for String;
20+
- impl<'a, T> FromIterator<T> for Cow<'a, [T]>
21+
where T: Clone;
22+
- impl<'a> FromIterator<char> for Cow<'a, str>;
23+
- impl<I> FromIterator<I> for Box<[I]>;
24+
- impl<T, S, A> FromIterator<T> for hashbrown::set::HashSet<T, S, A>
25+
where T: Eq, T: Hash, S: BuildHasher, S: Default, A: Default, A: Allocator, A: Clone;
26+
- impl<T, S> FromIterator<T> for HashSet<T, S>
27+
where T: Eq, T: Hash, S: BuildHasher, S: Default;
28+
- impl<T> FromIterator<T> for Arc<[T]>;
29+
- impl<T> FromIterator<T> for BTreeSet<T>
30+
where T: Ord;
31+
- impl<T> FromIterator<T> for BinaryHeap<T>
32+
where T: Ord;
33+
- impl<T> FromIterator<T> for LinkedList<T>;
34+
- impl<T> FromIterator<T> for Rc<[T]>;
35+
- impl<T> FromIterator<T> for Vec<T>;
36+
- impl<T> FromIterator<T> for VecDeque<T>;
37+
note: required by a bound in `collect`
38+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
39+
help: consider giving `x` an explicit type
40+
|
41+
LL | let x: Vec<_> = "hello".chars().rev().collect();
42+
| ++++++++
43+
44+
error: aborting due to 2 previous errors
1345

14-
For more information about this error, try `rustc --explain E0282`.
46+
Some errors have detailed explanations: E0282, E0283.
47+
For more information about an error, try `rustc --explain E0282`.
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
struct Foo {
2+
inner: u32,
3+
}
4+
5+
struct Bar {
6+
inner: u32,
7+
}
8+
9+
#[derive(Clone, Copy)]
10+
struct Baz {
11+
inner: u32,
12+
}
13+
14+
impl From<Baz> for Bar {
15+
fn from(other: Baz) -> Self {
16+
Self {
17+
inner: other.inner,
18+
}
19+
}
20+
}
21+
22+
impl From<Baz> for Foo {
23+
fn from(other: Baz) -> Self {
24+
Self {
25+
inner: other.inner,
26+
}
27+
}
28+
}
29+
30+
fn main() {
31+
let x: Baz = Baz { inner: 42 };
32+
33+
// DOESN'T Compile: Multiple options!
34+
let y = x.into();
35+
//~^ ERROR E0282
36+
//~| ERROR E0283
37+
38+
let y_1: Foo = x.into();
39+
let y_2: Bar = x.into();
40+
41+
let z_1 = Foo::from(y_1);
42+
let z_2 = Bar::from(y_2);
43+
44+
// No type annotations needed, the compiler KNOWS the type must be `Foo`!
45+
let m = magic_foo(x);
46+
}
47+
48+
fn magic_foo(arg: Baz) -> Foo {
49+
arg.into()
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/multiple-impl-apply.rs:34:9
3+
|
4+
LL | let y = x.into();
5+
| ^
6+
|
7+
help: consider giving `y` an explicit type
8+
|
9+
LL | let y: /* Type */ = x.into();
10+
| ++++++++++++
11+
12+
error[E0283]: type annotations needed
13+
--> $DIR/multiple-impl-apply.rs:34:9
14+
|
15+
LL | let y = x.into();
16+
| ^ ---- type must be known at this point
17+
|
18+
note: multiple `impl`s satisfying `_: From<Baz>` found
19+
--> $DIR/multiple-impl-apply.rs:14:1
20+
|
21+
LL | impl From<Baz> for Bar {
22+
| ^^^^^^^^^^^^^^^^^^^^^^
23+
...
24+
LL | impl From<Baz> for Foo {
25+
| ^^^^^^^^^^^^^^^^^^^^^^
26+
= note: required for `Baz` to implement `Into<_>`
27+
help: consider giving `y` an explicit type
28+
|
29+
LL | let y: /* Type */ = x.into();
30+
| ++++++++++++
31+
32+
error: aborting due to 2 previous errors
33+
34+
Some errors have detailed explanations: E0282, E0283.
35+
For more information about an error, try `rustc --explain E0282`.

tests/ui/inference/question-mark-type-infer.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn g() -> Result<Vec<i32>, ()> {
99
let l = [1, 2, 3, 4];
1010
l.iter().map(f).collect()?
1111
//~^ ERROR type annotations needed
12+
//~| ERROR type annotations needed
1213
}
1314

1415
fn main() {

tests/ui/inference/question-mark-type-infer.stderr

+17-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ help: consider specifying the generic argument
99
LL | l.iter().map(f).collect::<Vec<_>>()?
1010
| ++++++++++
1111

12-
error: aborting due to previous error
12+
error[E0283]: type annotations needed
13+
--> $DIR/question-mark-type-infer.rs:10:21
14+
|
15+
LL | l.iter().map(f).collect()?
16+
| ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
17+
|
18+
= note: cannot satisfy `_: FromIterator<Result<i32, ()>>`
19+
note: required by a bound in `collect`
20+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
21+
help: consider specifying the generic argument
22+
|
23+
LL | l.iter().map(f).collect::<Vec<_>>()?
24+
| ++++++++++
25+
26+
error: aborting due to 2 previous errors
1327

14-
For more information about this error, try `rustc --explain E0282`.
28+
Some errors have detailed explanations: E0282, E0283.
29+
For more information about an error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)