@@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax;
2
2
use rustc_errors:: codes:: * ;
3
3
use rustc_errors:: { Diag , EmissionGuarantee , ErrorGuaranteed , StashKey , Suggestions } ;
4
4
use 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 ;
6
7
use rustc_lint_defs:: Applicability ;
7
8
use rustc_lint_defs:: builtin:: BARE_TRAIT_OBJECTS ;
8
9
use rustc_span:: Span ;
10
+ use rustc_span:: edit_distance:: find_best_match_for_name;
9
11
use rustc_trait_selection:: error_reporting:: traits:: suggestions:: NextTypeParamName ;
10
12
11
13
use super :: HirTyLowerer ;
@@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
86
88
// Check if the impl trait that we are considering is an impl of a local trait.
87
89
self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
88
90
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
90
97
// Add the suggestion to this error
91
98
if let Some ( mut sugg) =
92
99
tcx. dcx ( ) . steal_non_err ( self_ty. span , StashKey :: AssociatedTypeSuggestion )
@@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
343
350
) ;
344
351
}
345
352
}
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
+ }
346
393
}
0 commit comments