@@ -141,6 +141,22 @@ struct BaseError {
141141 suggestion : Option < ( Span , & ' static str , String ) > ,
142142}
143143
144+ #[ derive( Debug ) ]
145+ enum TypoCandidate {
146+ Typo ( TypoSuggestion ) ,
147+ Shadowed ( Res ) ,
148+ None ,
149+ }
150+
151+ impl TypoCandidate {
152+ fn to_opt_suggestion ( self ) -> Option < TypoSuggestion > {
153+ match self {
154+ TypoCandidate :: Typo ( sugg) => Some ( sugg) ,
155+ TypoCandidate :: Shadowed ( _) | TypoCandidate :: None => None ,
156+ }
157+ }
158+ }
159+
144160impl < ' a : ' ast , ' ast > LateResolutionVisitor < ' a , ' _ , ' ast > {
145161 fn def_span ( & self , def_id : DefId ) -> Option < Span > {
146162 match def_id. krate {
@@ -497,7 +513,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
497513 }
498514
499515 // Try Levenshtein algorithm.
500- let typo_sugg = self . lookup_typo_candidate ( path, source. namespace ( ) , is_expected) ;
516+ let typo_sugg =
517+ self . lookup_typo_candidate ( path, source. namespace ( ) , is_expected) . to_opt_suggestion ( ) ;
501518 if path. len ( ) == 1 && self . self_type_is_available ( ) {
502519 if let Some ( candidate) = self . lookup_assoc_candidate ( ident, ns, is_expected) {
503520 let self_is_available = self . self_value_is_available ( path[ 0 ] . ident . span ) ;
@@ -661,7 +678,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
661678 let is_expected = & |res| source. is_expected ( res) ;
662679 let ident_span = path. last ( ) . map_or ( span, |ident| ident. ident . span ) ;
663680 let typo_sugg = self . lookup_typo_candidate ( path, source. namespace ( ) , is_expected) ;
681+ if let TypoCandidate :: Shadowed ( res) = typo_sugg
682+ && let Some ( id) = res. opt_def_id ( )
683+ && let Some ( sugg_span) = self . r . opt_span ( id)
684+ {
685+ err. span_label (
686+ sugg_span,
687+ format ! ( "you might have meant to refer to this {}" , res. descr( ) ) ,
688+ ) ;
689+ return true ;
690+ }
664691 let mut fallback = false ;
692+ let typo_sugg = typo_sugg. to_opt_suggestion ( ) ;
665693 if !self . r . add_typo_suggestion ( err, typo_sugg, ident_span) {
666694 fallback = true ;
667695 match self . diagnostic_metadata . current_let_binding {
@@ -1582,7 +1610,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
15821610 path : & [ Segment ] ,
15831611 ns : Namespace ,
15841612 filter_fn : & impl Fn ( Res ) -> bool ,
1585- ) -> Option < TypoSuggestion > {
1613+ ) -> TypoCandidate {
15861614 let mut names = Vec :: new ( ) ;
15871615 if path. len ( ) == 1 {
15881616 let mut ctxt = path. last ( ) . unwrap ( ) . ident . span . ctxt ( ) ;
@@ -1671,10 +1699,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
16711699 name,
16721700 None ,
16731701 ) {
1674- Some ( found) if found != name => {
1675- names. into_iter ( ) . find ( |suggestion| suggestion. candidate == found)
1702+ Some ( found) => {
1703+ let Some ( sugg) = names. into_iter ( ) . find ( |suggestion| suggestion. candidate == found) else {
1704+ return TypoCandidate :: None ;
1705+ } ;
1706+ if found == name {
1707+ TypoCandidate :: Shadowed ( sugg. res )
1708+ } else {
1709+ TypoCandidate :: Typo ( sugg)
1710+ }
16761711 }
1677- _ => None ,
1712+ _ => TypoCandidate :: None ,
16781713 }
16791714 }
16801715
0 commit comments