@@ -891,6 +891,10 @@ pub struct Resolver<'a> {
891891 /// "self-confirming" import resolutions during import validation.
892892 unusable_binding : Option < & ' a NameBinding < ' a > > ,
893893
894+ // Spans for local variables found during pattern resolution.
895+ // Used for suggestions during error reporting.
896+ pat_span_map : NodeMap < Span > ,
897+
894898 /// Resolutions for nodes that have a single resolution.
895899 partial_res_map : NodeMap < PartialRes > ,
896900 /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
@@ -1270,6 +1274,7 @@ impl<'a> Resolver<'a> {
12701274 last_import_segment : false ,
12711275 unusable_binding : None ,
12721276
1277+ pat_span_map : Default :: default ( ) ,
12731278 partial_res_map : Default :: default ( ) ,
12741279 import_res_map : Default :: default ( ) ,
12751280 label_res_map : Default :: default ( ) ,
@@ -1917,7 +1922,6 @@ impl<'a> Resolver<'a> {
19171922 return Some ( LexicalScopeBinding :: Item ( binding) ) ;
19181923 }
19191924 }
1920-
19211925 self . early_resolve_ident_in_lexical_scope (
19221926 orig_ident,
19231927 ScopeSet :: Late ( ns, module, record_used_id) ,
@@ -2394,7 +2398,59 @@ impl<'a> Resolver<'a> {
23942398 . next ( )
23952399 . map_or ( false , |c| c. is_ascii_uppercase ( ) )
23962400 {
2397- ( format ! ( "use of undeclared type `{}`" , ident) , None )
2401+ // Check whether the name refers to an item in the value namespace.
2402+ let suggestion = if ribs. is_some ( ) {
2403+ let match_span = match self . resolve_ident_in_lexical_scope (
2404+ ident,
2405+ ValueNS ,
2406+ parent_scope,
2407+ None ,
2408+ path_span,
2409+ & ribs. unwrap ( ) [ ValueNS ] ,
2410+ ) {
2411+ // Name matches a local variable. For example:
2412+ // ```
2413+ // fn f() {
2414+ // let Foo: &str = "";
2415+ // println!("{}", Foo::Bar); // Name refers to local
2416+ // // variable `Foo`.
2417+ // }
2418+ // ```
2419+ Some ( LexicalScopeBinding :: Res ( Res :: Local ( id) ) ) => {
2420+ Some ( * self . pat_span_map . get ( & id) . unwrap ( ) )
2421+ }
2422+
2423+ // Name matches item from a local name binding
2424+ // created by `use` declaration. For example:
2425+ // ```
2426+ // pub Foo: &str = "";
2427+ //
2428+ // mod submod {
2429+ // use super::Foo;
2430+ // println!("{}", Foo::Bar); // Name refers to local
2431+ // // binding `Foo`.
2432+ // }
2433+ // ```
2434+ Some ( LexicalScopeBinding :: Item ( name_binding) ) => {
2435+ Some ( name_binding. span )
2436+ }
2437+ _ => None ,
2438+ } ;
2439+
2440+ if let Some ( span) = match_span {
2441+ Some ( (
2442+ vec ! [ ( span, String :: from( "" ) ) ] ,
2443+ format ! ( "`{}` is defined here, but is not a type" , ident) ,
2444+ Applicability :: MaybeIncorrect ,
2445+ ) )
2446+ } else {
2447+ None
2448+ }
2449+ } else {
2450+ None
2451+ } ;
2452+
2453+ ( format ! ( "use of undeclared type `{}`" , ident) , suggestion)
23982454 } else {
23992455 ( format ! ( "use of undeclared crate or module `{}`" , ident) , None )
24002456 }
@@ -2805,6 +2861,11 @@ impl<'a> Resolver<'a> {
28052861 }
28062862 }
28072863
2864+ fn record_pat_span ( & mut self , node : NodeId , span : Span ) {
2865+ debug ! ( "(recording pat) recording {:?} for {:?}" , node, span) ;
2866+ self . pat_span_map . insert ( node, span) ;
2867+ }
2868+
28082869 fn is_accessible_from ( & self , vis : ty:: Visibility , module : Module < ' a > ) -> bool {
28092870 vis. is_accessible_from ( module. nearest_parent_mod , self )
28102871 }
0 commit comments