@@ -141,6 +141,22 @@ struct BaseError {
141
141
suggestion : Option < ( Span , & ' static str , String ) > ,
142
142
}
143
143
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
+
144
160
impl < ' a : ' ast , ' ast > LateResolutionVisitor < ' a , ' _ , ' ast > {
145
161
fn def_span ( & self , def_id : DefId ) -> Option < Span > {
146
162
match def_id. krate {
@@ -497,7 +513,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
497
513
}
498
514
499
515
// 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 ( ) ;
501
518
if path. len ( ) == 1 && self . self_type_is_available ( ) {
502
519
if let Some ( candidate) = self . lookup_assoc_candidate ( ident, ns, is_expected) {
503
520
let self_is_available = self . self_value_is_available ( path[ 0 ] . ident . span ) ;
@@ -661,7 +678,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
661
678
let is_expected = & |res| source. is_expected ( res) ;
662
679
let ident_span = path. last ( ) . map_or ( span, |ident| ident. ident . span ) ;
663
680
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
+ }
664
691
let mut fallback = false ;
692
+ let typo_sugg = typo_sugg. to_opt_suggestion ( ) ;
665
693
if !self . r . add_typo_suggestion ( err, typo_sugg, ident_span) {
666
694
fallback = true ;
667
695
match self . diagnostic_metadata . current_let_binding {
@@ -1582,7 +1610,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1582
1610
path : & [ Segment ] ,
1583
1611
ns : Namespace ,
1584
1612
filter_fn : & impl Fn ( Res ) -> bool ,
1585
- ) -> Option < TypoSuggestion > {
1613
+ ) -> TypoCandidate {
1586
1614
let mut names = Vec :: new ( ) ;
1587
1615
if path. len ( ) == 1 {
1588
1616
let mut ctxt = path. last ( ) . unwrap ( ) . ident . span . ctxt ( ) ;
@@ -1671,10 +1699,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
1671
1699
name,
1672
1700
None ,
1673
1701
) {
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
+ }
1676
1711
}
1677
- _ => None ,
1712
+ _ => TypoCandidate :: None ,
1678
1713
}
1679
1714
}
1680
1715
0 commit comments