diff options
| author | bors <bors@rust-lang.org> | 2022-04-30 18:44:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-04-30 18:44:01 +0000 |
| commit | 7c4b47696907d64eff5621a64eb3c6e795a9ec77 (patch) | |
| tree | 6741f99bbc2c7b939e2488b2f4e8302a3b9badbd /compiler | |
| parent | 579d26876ddc5426be32cca1a026b6fd7fc5be24 (diff) | |
| parent | a7213832618f25690a65b5c270309df687d6b869 (diff) | |
| download | rust-7c4b47696907d64eff5621a64eb3c6e795a9ec77.tar.gz rust-7c4b47696907d64eff5621a64eb3c6e795a9ec77.zip | |
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
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs | 41 |
1 files changed, 31 insertions, 10 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..465358de932 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 @@ -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), + } + } +} |
