@@ -891,6 +891,10 @@ pub struct Resolver<'a> {
891
891
/// "self-confirming" import resolutions during import validation.
892
892
unusable_binding : Option < & ' a NameBinding < ' a > > ,
893
893
894
+ // Spans for local variables found during pattern resolution.
895
+ // Used for suggestions during error reporting.
896
+ pat_span_map : NodeMap < Span > ,
897
+
894
898
/// Resolutions for nodes that have a single resolution.
895
899
partial_res_map : NodeMap < PartialRes > ,
896
900
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
@@ -1270,6 +1274,7 @@ impl<'a> Resolver<'a> {
1270
1274
last_import_segment : false ,
1271
1275
unusable_binding : None ,
1272
1276
1277
+ pat_span_map : Default :: default ( ) ,
1273
1278
partial_res_map : Default :: default ( ) ,
1274
1279
import_res_map : Default :: default ( ) ,
1275
1280
label_res_map : Default :: default ( ) ,
@@ -1917,7 +1922,6 @@ impl<'a> Resolver<'a> {
1917
1922
return Some ( LexicalScopeBinding :: Item ( binding) ) ;
1918
1923
}
1919
1924
}
1920
-
1921
1925
self . early_resolve_ident_in_lexical_scope (
1922
1926
orig_ident,
1923
1927
ScopeSet :: Late ( ns, module, record_used_id) ,
@@ -2394,7 +2398,59 @@ impl<'a> Resolver<'a> {
2394
2398
. next ( )
2395
2399
. map_or ( false , |c| c. is_ascii_uppercase ( ) )
2396
2400
{
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)
2398
2454
} else {
2399
2455
( format ! ( "use of undeclared crate or module `{}`" , ident) , None )
2400
2456
}
@@ -2805,6 +2861,11 @@ impl<'a> Resolver<'a> {
2805
2861
}
2806
2862
}
2807
2863
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
+
2808
2869
fn is_accessible_from ( & self , vis : ty:: Visibility , module : Module < ' a > ) -> bool {
2809
2870
vis. is_accessible_from ( module. nearest_parent_mod , self )
2810
2871
}
0 commit comments