@@ -38,14 +38,25 @@ crate type Suggestion = (Vec<(Span, String)>, String, Applicability);
3838/// similarly named label and whether or not it is reachable.
3939crate type LabelSuggestion = ( Ident , bool ) ;
4040
41+ crate enum SuggestionTarget {
42+ /// The target has a similar name as the name used by the programmer (probably a typo)
43+ SimilarlyNamed ,
44+ /// The target is the only valid item that can be used in the corresponding context
45+ SingleItem ,
46+ }
47+
4148crate struct TypoSuggestion {
4249 pub candidate : Symbol ,
4350 pub res : Res ,
51+ pub target : SuggestionTarget ,
4452}
4553
4654impl TypoSuggestion {
47- crate fn from_res ( candidate : Symbol , res : Res ) -> TypoSuggestion {
48- TypoSuggestion { candidate, res }
55+ crate fn typo_from_res ( candidate : Symbol , res : Res ) -> TypoSuggestion {
56+ Self { candidate, res, target : SuggestionTarget :: SimilarlyNamed }
57+ }
58+ crate fn single_item_from_res ( candidate : Symbol , res : Res ) -> TypoSuggestion {
59+ Self { candidate, res, target : SuggestionTarget :: SingleItem }
4960 }
5061}
5162
@@ -80,7 +91,7 @@ impl<'a> Resolver<'a> {
8091 if let Some ( binding) = resolution. borrow ( ) . binding {
8192 let res = binding. res ( ) ;
8293 if filter_fn ( res) {
83- names. push ( TypoSuggestion :: from_res ( key. ident . name , res) ) ;
94+ names. push ( TypoSuggestion :: typo_from_res ( key. ident . name , res) ) ;
8495 }
8596 }
8697 }
@@ -623,7 +634,7 @@ impl<'a> Resolver<'a> {
623634 . get ( & expn_id)
624635 . into_iter ( )
625636 . flatten ( )
626- . map ( |ident| TypoSuggestion :: from_res ( ident. name , res) ) ,
637+ . map ( |ident| TypoSuggestion :: typo_from_res ( ident. name , res) ) ,
627638 ) ;
628639 }
629640 }
@@ -642,7 +653,7 @@ impl<'a> Resolver<'a> {
642653 suggestions. extend (
643654 ext. helper_attrs
644655 . iter ( )
645- . map ( |name| TypoSuggestion :: from_res ( * name, res) ) ,
656+ . map ( |name| TypoSuggestion :: typo_from_res ( * name, res) ) ,
646657 ) ;
647658 }
648659 }
@@ -652,8 +663,10 @@ impl<'a> Resolver<'a> {
652663 if let MacroRulesScope :: Binding ( macro_rules_binding) = macro_rules_scope. get ( ) {
653664 let res = macro_rules_binding. binding . res ( ) ;
654665 if filter_fn ( res) {
655- suggestions
656- . push ( TypoSuggestion :: from_res ( macro_rules_binding. ident . name , res) )
666+ suggestions. push ( TypoSuggestion :: typo_from_res (
667+ macro_rules_binding. ident . name ,
668+ res,
669+ ) )
657670 }
658671 }
659672 }
@@ -671,15 +684,15 @@ impl<'a> Resolver<'a> {
671684 suggestions. extend (
672685 this. registered_attrs
673686 . iter ( )
674- . map ( |ident| TypoSuggestion :: from_res ( ident. name , res) ) ,
687+ . map ( |ident| TypoSuggestion :: typo_from_res ( ident. name , res) ) ,
675688 ) ;
676689 }
677690 }
678691 Scope :: MacroUsePrelude => {
679692 suggestions. extend ( this. macro_use_prelude . iter ( ) . filter_map (
680693 |( name, binding) | {
681694 let res = binding. res ( ) ;
682- filter_fn ( res) . then_some ( TypoSuggestion :: from_res ( * name, res) )
695+ filter_fn ( res) . then_some ( TypoSuggestion :: typo_from_res ( * name, res) )
683696 } ,
684697 ) ) ;
685698 }
@@ -689,22 +702,22 @@ impl<'a> Resolver<'a> {
689702 suggestions. extend (
690703 BUILTIN_ATTRIBUTES
691704 . iter ( )
692- . map ( |( name, ..) | TypoSuggestion :: from_res ( * name, res) ) ,
705+ . map ( |( name, ..) | TypoSuggestion :: typo_from_res ( * name, res) ) ,
693706 ) ;
694707 }
695708 }
696709 Scope :: ExternPrelude => {
697710 suggestions. extend ( this. extern_prelude . iter ( ) . filter_map ( |( ident, _) | {
698711 let res = Res :: Def ( DefKind :: Mod , DefId :: local ( CRATE_DEF_INDEX ) ) ;
699- filter_fn ( res) . then_some ( TypoSuggestion :: from_res ( ident. name , res) )
712+ filter_fn ( res) . then_some ( TypoSuggestion :: typo_from_res ( ident. name , res) )
700713 } ) ) ;
701714 }
702715 Scope :: ToolPrelude => {
703716 let res = Res :: NonMacroAttr ( NonMacroAttrKind :: Tool ) ;
704717 suggestions. extend (
705718 this. registered_tools
706719 . iter ( )
707- . map ( |ident| TypoSuggestion :: from_res ( ident. name , res) ) ,
720+ . map ( |ident| TypoSuggestion :: typo_from_res ( ident. name , res) ) ,
708721 ) ;
709722 }
710723 Scope :: StdLibPrelude => {
@@ -721,7 +734,7 @@ impl<'a> Resolver<'a> {
721734 Scope :: BuiltinTypes => {
722735 suggestions. extend ( PrimTy :: ALL . iter ( ) . filter_map ( |prim_ty| {
723736 let res = Res :: PrimTy ( * prim_ty) ;
724- filter_fn ( res) . then_some ( TypoSuggestion :: from_res ( prim_ty. name ( ) , res) )
737+ filter_fn ( res) . then_some ( TypoSuggestion :: typo_from_res ( prim_ty. name ( ) , res) )
725738 } ) )
726739 }
727740 }
@@ -993,20 +1006,31 @@ impl<'a> Resolver<'a> {
9931006 // | ^
9941007 return false ;
9951008 }
1009+ let prefix = match suggestion. target {
1010+ SuggestionTarget :: SimilarlyNamed => "similarly named " ,
1011+ SuggestionTarget :: SingleItem => "" ,
1012+ } ;
1013+
9961014 err. span_label (
9971015 self . session . source_map ( ) . guess_head_span ( def_span) ,
9981016 & format ! (
999- "similarly named {} `{}` defined here" ,
1017+ "{}{} `{}` defined here" ,
1018+ prefix,
10001019 suggestion. res. descr( ) ,
10011020 suggestion. candidate. as_str( ) ,
10021021 ) ,
10031022 ) ;
10041023 }
1005- let msg = format ! (
1006- "{} {} with a similar name exists" ,
1007- suggestion. res. article( ) ,
1008- suggestion. res. descr( )
1009- ) ;
1024+ let msg = match suggestion. target {
1025+ SuggestionTarget :: SimilarlyNamed => format ! (
1026+ "{} {} with a similar name exists" ,
1027+ suggestion. res. article( ) ,
1028+ suggestion. res. descr( )
1029+ ) ,
1030+ SuggestionTarget :: SingleItem => {
1031+ format ! ( "maybe you meant this {}" , suggestion. res. descr( ) )
1032+ }
1033+ } ;
10101034 err. span_suggestion (
10111035 span,
10121036 & msg,
0 commit comments