mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Auto merge of #96347 - estebank:issue-96292, r=compiler-errors
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:
commit
7c4b476969
@ -734,22 +734,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
if !impl_candidates.is_empty() && e.span.contains(span)
|
||||
&& let Some(expr) = exprs.first()
|
||||
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
|
||||
&& let [path_segment] = path.segments
|
||||
&& let [_] = path.segments
|
||||
{
|
||||
let mut eraser = TypeParamEraser(self.tcx);
|
||||
let candidate_len = impl_candidates.len();
|
||||
let suggestions = impl_candidates.iter().map(|candidate| {
|
||||
format!(
|
||||
"{}::{}({})",
|
||||
candidate, segment.ident, path_segment.ident
|
||||
)
|
||||
});
|
||||
err.span_suggestions(
|
||||
e.span,
|
||||
let mut suggestions: Vec<_> = impl_candidates.iter().map(|candidate| {
|
||||
let candidate = candidate.super_fold_with(&mut eraser);
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), format!("{}::{}(", candidate, segment.ident)),
|
||||
if exprs.len() == 1 {
|
||||
(expr.span.shrink_to_hi().with_hi(e.span.hi()), ")".to_string())
|
||||
} else {
|
||||
(expr.span.shrink_to_hi().with_hi(exprs[1].span.lo()), ", ".to_string())
|
||||
},
|
||||
]
|
||||
}).collect();
|
||||
suggestions.sort_by(|a, b| a[0].1.cmp(&b[0].1));
|
||||
err.multipart_suggestions(
|
||||
&format!(
|
||||
"use the fully qualified path for the potential candidate{}",
|
||||
pluralize!(candidate_len),
|
||||
),
|
||||
suggestions,
|
||||
suggestions.into_iter(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -1037,3 +1043,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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ LL | let bar = foo_impl.into() * 1u32;
|
||||
| | |
|
||||
| | cannot infer type for type parameter `T` declared on the trait `Into`
|
||||
| this method call resolves to `T`
|
||||
| help: use the fully qualified path for the potential candidate: `<Impl as Into<u32>>::into(foo_impl)`
|
||||
|
|
||||
note: multiple `impl`s satisfying `Impl: Into<_>` found
|
||||
--> $DIR/E0283.rs:17:1
|
||||
@ -24,6 +23,10 @@ LL | impl Into<u32> for Impl {
|
||||
= note: and another `impl` found in the `core` crate:
|
||||
- impl<T, U> Into<U> for T
|
||||
where U: From<T>;
|
||||
help: use the fully qualified path for the potential candidate
|
||||
|
|
||||
LL | let bar = <Impl as Into<u32>>::into(foo_impl) * 1u32;
|
||||
| ++++++++++++++++++++++++++ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,20 @@
|
||||
struct Thing<X>(X);
|
||||
|
||||
trait Method<T> {
|
||||
fn method(self, _: i32) -> T;
|
||||
}
|
||||
|
||||
impl<X> Method<i32> for Thing<X> {
|
||||
fn method(self, _: i32) -> i32 { 0 }
|
||||
}
|
||||
|
||||
impl<X> Method<u32> for Thing<X> {
|
||||
fn method(self, _: i32) -> u32 { 0 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let thing = Thing(true);
|
||||
thing.method(42);
|
||||
//~^ ERROR type annotations needed
|
||||
//~| ERROR type annotations needed
|
||||
}
|
@ -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(42);
|
||||
| ------^^^^^^----
|
||||
| | |
|
||||
| | 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(42);
|
||||
| ------^^^^^^----
|
||||
| | |
|
||||
| | 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, 42);
|
||||
| ++++++++++++++++++++++++++++++++++ ~
|
||||
LL | <Thing<_> as Method<u32>>::method(thing, 42);
|
||||
| ++++++++++++++++++++++++++++++++++ ~
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0283.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
@ -37,13 +37,13 @@ LL | opts.get(opt.as_ref());
|
||||
help: use the fully qualified path for the potential candidates
|
||||
|
|
||||
LL | opts.get(<String as AsRef<OsStr>>::as_ref(opt));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| +++++++++++++++++++++++++++++++++ ~
|
||||
LL | opts.get(<String as AsRef<Path>>::as_ref(opt));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| ++++++++++++++++++++++++++++++++ ~
|
||||
LL | opts.get(<String as AsRef<[u8]>>::as_ref(opt));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| ++++++++++++++++++++++++++++++++ ~
|
||||
LL | opts.get(<String as AsRef<str>>::as_ref(opt));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
| +++++++++++++++++++++++++++++++ ~
|
||||
and 4 other candidates
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
|
Loading…
Reference in New Issue
Block a user