1
Fork 0

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
This commit is contained in:
Esteban Küber 2022-04-23 11:22:51 -07:00
parent 1e9aa8a96b
commit acee1f47ef
3 changed files with 74 additions and 0 deletions

View file

@ -736,8 +736,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
&& let [path_segment] = path.segments
{
let mut eraser = TypeParamEraser(self.tcx);
let candidate_len = impl_candidates.len();
let suggestions = impl_candidates.iter().map(|candidate| {
let candidate = candidate.super_fold_with(&mut eraser);
format!(
"{}::{}({})",
candidate, segment.ident, path_segment.ident
@ -1037,3 +1039,18 @@ impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> {
}
}
}
/// Replace type parameters with `ty::Infer(ty::Var)` to display `_`.
struct TypeParamEraser<'tcx>(TyCtxt<'tcx>);
impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
self.0
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.kind() {
ty::Param(_) | ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)),
_ => t.super_fold_with(self),
}
}
}

View file

@ -0,0 +1,20 @@
struct Thing<X>(X);
trait Method<T> {
fn method(self) -> T;
}
impl<X> Method<i32> for Thing<X> {
fn method(self) -> i32 { 0 }
}
impl<X> Method<u32> for Thing<X> {
fn method(self) -> u32 { 0 }
}
fn main() {
let thing = Thing(true);
thing.method();
//~^ ERROR type annotations needed
//~| ERROR type annotations needed
}

View file

@ -0,0 +1,37 @@
error[E0282]: type annotations needed
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
|
LL | thing.method();
| ------^^^^^^--
| | |
| | cannot infer type for type parameter `T` declared on the trait `Method`
| this method call resolves to `T`
error[E0283]: type annotations needed
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
|
LL | thing.method();
| ------^^^^^^--
| | |
| | cannot infer type for type parameter `T` declared on the trait `Method`
| this method call resolves to `T`
|
note: multiple `impl`s satisfying `Thing<bool>: Method<_>` found
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1
|
LL | impl<X> Method<i32> for Thing<X> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | impl<X> Method<u32> for Thing<X> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use the fully qualified path for the potential candidates
|
LL | <Thing<_> as Method<i32>>::method(thing);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL | <Thing<_> as Method<u32>>::method(thing);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0283.
For more information about an error, try `rustc --explain E0282`.