@@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax;
22use rustc_errors:: codes:: * ;
33use rustc_errors:: { Diag , EmissionGuarantee , ErrorGuaranteed , StashKey , Suggestions } ;
44use rustc_hir as hir;
5- use rustc_hir:: def:: { DefKind , Res } ;
5+ use rustc_hir:: def:: { DefKind , Namespace , Res } ;
6+ use rustc_hir:: def_id:: DefId ;
67use rustc_lint_defs:: Applicability ;
78use rustc_lint_defs:: builtin:: BARE_TRAIT_OBJECTS ;
89use rustc_span:: Span ;
10+ use rustc_span:: edit_distance:: find_best_match_for_name;
911use rustc_trait_selection:: error_reporting:: traits:: suggestions:: NextTypeParamName ;
1012
1113use super :: HirTyLowerer ;
@@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8688 // Check if the impl trait that we are considering is an impl of a local trait.
8789 self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
8890 self . maybe_suggest_assoc_ty_bound ( self_ty, & mut diag) ;
89- // In case there is an associate type with the same name
91+ self . maybe_suggest_typoed_method (
92+ self_ty,
93+ poly_trait_ref. trait_ref . trait_def_id ( ) ,
94+ & mut diag,
95+ ) ;
96+ // In case there is an associated type with the same name
9097 // Add the suggestion to this error
9198 if let Some ( mut sugg) =
9299 tcx. dcx ( ) . steal_non_err ( self_ty. span , StashKey :: AssociatedTypeSuggestion )
@@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
343350 ) ;
344351 }
345352 }
353+
354+ fn maybe_suggest_typoed_method (
355+ & self ,
356+ self_ty : & hir:: Ty < ' _ > ,
357+ trait_def_id : Option < DefId > ,
358+ diag : & mut Diag < ' _ > ,
359+ ) {
360+ let tcx = self . tcx ( ) ;
361+ let Some ( trait_def_id) = trait_def_id else {
362+ return ;
363+ } ;
364+ let hir:: Node :: Expr ( hir:: Expr {
365+ kind : hir:: ExprKind :: Path ( hir:: QPath :: TypeRelative ( path_ty, segment) ) ,
366+ ..
367+ } ) = tcx. parent_hir_node ( self_ty. hir_id )
368+ else {
369+ return ;
370+ } ;
371+ if path_ty. hir_id != self_ty. hir_id {
372+ return ;
373+ }
374+ let names: Vec < _ > = tcx
375+ . associated_items ( trait_def_id)
376+ . in_definition_order ( )
377+ . filter ( |assoc| assoc. kind . namespace ( ) == Namespace :: ValueNS )
378+ . map ( |cand| cand. name )
379+ . collect ( ) ;
380+ if let Some ( typo) = find_best_match_for_name ( & names, segment. ident . name , None ) {
381+ diag. span_suggestion_verbose (
382+ segment. ident . span ,
383+ format ! (
384+ "you may have misspelled this associated item, causing `{}` \
385+ to be interpreted as a type rather than a trait",
386+ tcx. item_name( trait_def_id) ,
387+ ) ,
388+ typo,
389+ Applicability :: MaybeIncorrect ,
390+ ) ;
391+ }
392+ }
346393}
0 commit comments