Skip to content

Commit acee1f4

Browse files
committed
Erase type params when suggesting fully qualified path
When suggesting the use of a fully qualified path for a method call that is ambiguous because it has multiple candidates, erase type params in the resulting code, as they would result in an error when applied. We replace them with `_` in the output to rely on inference. There might be cases where this still produces slighlty incomplete suggestions, but it otherwise produces many more errors in relatively common cases. Fix #96292
1 parent 1e9aa8a commit acee1f4

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
736736
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
737737
&& let [path_segment] = path.segments
738738
{
739+
let mut eraser = TypeParamEraser(self.tcx);
739740
let candidate_len = impl_candidates.len();
740741
let suggestions = impl_candidates.iter().map(|candidate| {
742+
let candidate = candidate.super_fold_with(&mut eraser);
741743
format!(
742744
"{}::{}({})",
743745
candidate, segment.ident, path_segment.ident
@@ -1037,3 +1039,18 @@ impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> {
10371039
}
10381040
}
10391041
}
1042+
1043+
/// Replace type parameters with `ty::Infer(ty::Var)` to display `_`.
1044+
struct TypeParamEraser<'tcx>(TyCtxt<'tcx>);
1045+
1046+
impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'tcx> {
1047+
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
1048+
self.0
1049+
}
1050+
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1051+
match t.kind() {
1052+
ty::Param(_) | ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)),
1053+
_ => t.super_fold_with(self),
1054+
}
1055+
}
1056+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
struct Thing<X>(X);
2+
3+
trait Method<T> {
4+
fn method(self) -> T;
5+
}
6+
7+
impl<X> Method<i32> for Thing<X> {
8+
fn method(self) -> i32 { 0 }
9+
}
10+
11+
impl<X> Method<u32> for Thing<X> {
12+
fn method(self) -> u32 { 0 }
13+
}
14+
15+
fn main() {
16+
let thing = Thing(true);
17+
thing.method();
18+
//~^ ERROR type annotations needed
19+
//~| ERROR type annotations needed
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
3+
|
4+
LL | thing.method();
5+
| ------^^^^^^--
6+
| | |
7+
| | cannot infer type for type parameter `T` declared on the trait `Method`
8+
| this method call resolves to `T`
9+
10+
error[E0283]: type annotations needed
11+
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
12+
|
13+
LL | thing.method();
14+
| ------^^^^^^--
15+
| | |
16+
| | cannot infer type for type parameter `T` declared on the trait `Method`
17+
| this method call resolves to `T`
18+
|
19+
note: multiple `impl`s satisfying `Thing<bool>: Method<_>` found
20+
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1
21+
|
22+
LL | impl<X> Method<i32> for Thing<X> {
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
...
25+
LL | impl<X> Method<u32> for Thing<X> {
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
help: use the fully qualified path for the potential candidates
28+
|
29+
LL | <Thing<_> as Method<i32>>::method(thing);
30+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31+
LL | <Thing<_> as Method<u32>>::method(thing);
32+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33+
34+
error: aborting due to 2 previous errors
35+
36+
Some errors have detailed explanations: E0282, E0283.
37+
For more information about an error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)