Suggest typos when trait path expression is typod
This commit is contained in:
parent
336209eef1
commit
4486a19007
3 changed files with 79 additions and 2 deletions
|
@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def::{DefKind, Namespace, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
|
||||
|
||||
use super::HirTyLowerer;
|
||||
|
@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Check if the impl trait that we are considering is an impl of a local trait.
|
||||
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
|
||||
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
|
||||
// In case there is an associate type with the same name
|
||||
self.maybe_suggest_typoed_method(
|
||||
self_ty,
|
||||
poly_trait_ref.trait_ref.trait_def_id(),
|
||||
&mut diag,
|
||||
);
|
||||
// In case there is an associated type with the same name
|
||||
// Add the suggestion to this error
|
||||
if let Some(mut sugg) =
|
||||
tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion)
|
||||
|
@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_suggest_typoed_method(
|
||||
&self,
|
||||
self_ty: &hir::Ty<'_>,
|
||||
trait_def_id: Option<DefId>,
|
||||
diag: &mut Diag<'_>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
let Some(trait_def_id) = trait_def_id else {
|
||||
return;
|
||||
};
|
||||
let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
|
||||
..
|
||||
}) = tcx.parent_hir_node(self_ty.hir_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if path_ty.hir_id != self_ty.hir_id {
|
||||
return;
|
||||
}
|
||||
let names: Vec<_> = tcx
|
||||
.associated_items(trait_def_id)
|
||||
.in_definition_order()
|
||||
.filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS)
|
||||
.map(|cand| cand.name)
|
||||
.collect();
|
||||
if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
|
||||
diag.span_suggestion_verbose(
|
||||
segment.ident.span,
|
||||
format!(
|
||||
"you may have misspelled this associated item, causing `{}` \
|
||||
to be interpreted as a type rather than a trait",
|
||||
tcx.item_name(trait_def_id),
|
||||
),
|
||||
typo,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue