diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2022-04-23 11:22:51 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2022-04-23 11:31:41 -0700 |
| commit | acee1f47ef5d75bc9f9043f2be59e4e6ced6892b (patch) | |
| tree | 284f45c579cbbdfb9470c775f9cbbc577c119701 | |
| parent | 1e9aa8a96b207668799365bf891a459b62410b60 (diff) | |
| download | rust-acee1f47ef5d75bc9f9043f2be59e4e6ced6892b.tar.gz rust-acee1f47ef5d75bc9f9043f2be59e4e6ced6892b.zip | |
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
3 files changed, 74 insertions, 0 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index a9a92fdbd64..c851d12b3e6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -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), + } + } +} diff --git a/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs new file mode 100644 index 00000000000..f08025d99b5 --- /dev/null +++ b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs @@ -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 +} diff --git a/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr new file mode 100644 index 00000000000..2e80fa89f63 --- /dev/null +++ b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -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`. |
