@@ -316,22 +316,8 @@ impl<'a> PathSource<'a> {
316316 }
317317}
318318
319- struct LateResolutionVisitor < ' a , ' b > {
320- r : & ' b mut Resolver < ' a > ,
321-
322- /// The module that represents the current item scope.
323- parent_scope : ParentScope < ' a > ,
324-
325- /// The current set of local scopes for types and values.
326- /// FIXME #4948: Reuse ribs to avoid allocation.
327- ribs : PerNS < Vec < Rib < ' a > > > ,
328-
329- /// The current set of local scopes, for labels.
330- label_ribs : Vec < Rib < ' a , NodeId > > ,
331-
332- /// The trait that the current context can refer to.
333- current_trait_ref : Option < ( Module < ' a > , TraitRef ) > ,
334-
319+ #[ derive( Default ) ]
320+ struct DiagnosticMetadata {
335321 /// The current trait's associated types' ident, used for diagnostic suggestions.
336322 current_trait_assoc_types : Vec < Ident > ,
337323
@@ -350,6 +336,29 @@ struct LateResolutionVisitor<'a, 'b> {
350336
351337 /// Only used for better errors on `fn(): fn()`.
352338 current_type_ascription : Vec < Span > ,
339+
340+ /// Only used for better errors on `let <pat>: <expr, not type>;`.
341+ current_let_binding : Option < ( Span , Option < Span > , Option < Span > ) > ,
342+ }
343+
344+ struct LateResolutionVisitor < ' a , ' b > {
345+ r : & ' b mut Resolver < ' a > ,
346+
347+ /// The module that represents the current item scope.
348+ parent_scope : ParentScope < ' a > ,
349+
350+ /// The current set of local scopes for types and values.
351+ /// FIXME #4948: Reuse ribs to avoid allocation.
352+ ribs : PerNS < Vec < Rib < ' a > > > ,
353+
354+ /// The current set of local scopes, for labels.
355+ label_ribs : Vec < Rib < ' a , NodeId > > ,
356+
357+ /// The trait that the current context can refer to.
358+ current_trait_ref : Option < ( Module < ' a > , TraitRef ) > ,
359+
360+ /// Fields used to add information to diagnostic errors.
361+ diagnostic_metadata : DiagnosticMetadata ,
353362}
354363
355364/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
@@ -373,7 +382,18 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
373382 self . resolve_expr ( expr, None ) ;
374383 }
375384 fn visit_local ( & mut self , local : & ' tcx Local ) {
385+ let local_spans = match local. pat . kind {
386+ // We check for this to avoid tuple struct fields.
387+ PatKind :: Wild => None ,
388+ _ => Some ( (
389+ local. pat . span ,
390+ local. ty . as_ref ( ) . map ( |ty| ty. span ) ,
391+ local. init . as_ref ( ) . map ( |init| init. span ) ,
392+ ) ) ,
393+ } ;
394+ let original = replace ( & mut self . diagnostic_metadata . current_let_binding , local_spans) ;
376395 self . resolve_local ( local) ;
396+ self . diagnostic_metadata . current_let_binding = original;
377397 }
378398 fn visit_ty ( & mut self , ty : & ' tcx Ty ) {
379399 match ty. kind {
@@ -415,7 +435,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
415435 }
416436 }
417437 fn visit_fn ( & mut self , fn_kind : FnKind < ' tcx > , declaration : & ' tcx FnDecl , sp : Span , _: NodeId ) {
418- let previous_value = replace ( & mut self . current_function , Some ( sp) ) ;
438+ let previous_value = replace ( & mut self . diagnostic_metadata . current_function , Some ( sp) ) ;
419439 debug ! ( "(resolving function) entering function" ) ;
420440 let rib_kind = match fn_kind {
421441 FnKind :: ItemFn ( ..) => FnItemRibKind ,
@@ -441,7 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
441461 debug ! ( "(resolving function) leaving function" ) ;
442462 } )
443463 } ) ;
444- self . current_function = previous_value;
464+ self . diagnostic_metadata . current_function = previous_value;
445465 }
446466
447467 fn visit_generics ( & mut self , generics : & ' tcx Generics ) {
@@ -475,7 +495,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> {
475495 // (We however cannot ban `Self` for defaults on *all* generic
476496 // lists; e.g. trait generics can usefully refer to `Self`,
477497 // such as in the case of `trait Add<Rhs = Self>`.)
478- if self . current_self_item . is_some ( ) { // (`Some` if + only if we are in ADT's generics.)
498+ if self . diagnostic_metadata . current_self_item . is_some ( ) {
499+ // (`Some` if + only if we are in ADT's generics.)
479500 default_ban_rib. bindings . insert ( Ident :: with_dummy_span ( kw:: SelfUpper ) , Res :: Err ) ;
480501 }
481502
@@ -527,12 +548,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
527548 } ,
528549 label_ribs : Vec :: new ( ) ,
529550 current_trait_ref : None ,
530- current_trait_assoc_types : Vec :: new ( ) ,
531- current_self_type : None ,
532- current_self_item : None ,
533- current_function : None ,
534- unused_labels : Default :: default ( ) ,
535- current_type_ascription : Vec :: new ( ) ,
551+ diagnostic_metadata : DiagnosticMetadata :: default ( ) ,
536552 }
537553 }
538554
@@ -892,16 +908,22 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
892908
893909 fn with_current_self_type < T > ( & mut self , self_type : & Ty , f : impl FnOnce ( & mut Self ) -> T ) -> T {
894910 // Handle nested impls (inside fn bodies)
895- let previous_value = replace ( & mut self . current_self_type , Some ( self_type. clone ( ) ) ) ;
911+ let previous_value = replace (
912+ & mut self . diagnostic_metadata . current_self_type ,
913+ Some ( self_type. clone ( ) ) ,
914+ ) ;
896915 let result = f ( self ) ;
897- self . current_self_type = previous_value;
916+ self . diagnostic_metadata . current_self_type = previous_value;
898917 result
899918 }
900919
901920 fn with_current_self_item < T > ( & mut self , self_item : & Item , f : impl FnOnce ( & mut Self ) -> T ) -> T {
902- let previous_value = replace ( & mut self . current_self_item , Some ( self_item. id ) ) ;
921+ let previous_value = replace (
922+ & mut self . diagnostic_metadata . current_self_item ,
923+ Some ( self_item. id ) ,
924+ ) ;
903925 let result = f ( self ) ;
904- self . current_self_item = previous_value;
926+ self . diagnostic_metadata . current_self_item = previous_value;
905927 result
906928 }
907929
@@ -912,14 +934,14 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
912934 f : impl FnOnce ( & mut Self ) -> T ,
913935 ) -> T {
914936 let trait_assoc_types = replace (
915- & mut self . current_trait_assoc_types ,
937+ & mut self . diagnostic_metadata . current_trait_assoc_types ,
916938 trait_items. iter ( ) . filter_map ( |item| match & item. kind {
917939 TraitItemKind :: Type ( bounds, _) if bounds. len ( ) == 0 => Some ( item. ident ) ,
918940 _ => None ,
919941 } ) . collect ( ) ,
920942 ) ;
921943 let result = f ( self ) ;
922- self . current_trait_assoc_types = trait_assoc_types;
944+ self . diagnostic_metadata . current_trait_assoc_types = trait_assoc_types;
923945 result
924946 }
925947
@@ -1746,7 +1768,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
17461768
17471769 fn with_resolved_label ( & mut self , label : Option < Label > , id : NodeId , f : impl FnOnce ( & mut Self ) ) {
17481770 if let Some ( label) = label {
1749- self . unused_labels . insert ( id, label. ident . span ) ;
1771+ self . diagnostic_metadata . unused_labels . insert ( id, label. ident . span ) ;
17501772 self . with_label_rib ( NormalRibKind , |this| {
17511773 let ident = label. ident . modern_and_legacy ( ) ;
17521774 this. label_ribs . last_mut ( ) . unwrap ( ) . bindings . insert ( ident, id) ;
@@ -1850,7 +1872,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
18501872 Some ( node_id) => {
18511873 // Since this res is a label, it is never read.
18521874 self . r . label_res_map . insert ( expr. id , node_id) ;
1853- self . unused_labels . remove ( & node_id) ;
1875+ self . diagnostic_metadata . unused_labels . remove ( & node_id) ;
18541876 }
18551877 }
18561878
@@ -1912,9 +1934,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
19121934 }
19131935 }
19141936 ExprKind :: Type ( ref type_expr, _) => {
1915- self . current_type_ascription . push ( type_expr. span ) ;
1937+ self . diagnostic_metadata . current_type_ascription . push ( type_expr. span ) ;
19161938 visit:: walk_expr ( self , expr) ;
1917- self . current_type_ascription . pop ( ) ;
1939+ self . diagnostic_metadata . current_type_ascription . pop ( ) ;
19181940 }
19191941 // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
19201942 // resolve the arguments within the proper scopes so that usages of them inside the
@@ -2073,7 +2095,7 @@ impl<'a> Resolver<'a> {
20732095 pub ( crate ) fn late_resolve_crate ( & mut self , krate : & Crate ) {
20742096 let mut late_resolution_visitor = LateResolutionVisitor :: new ( self ) ;
20752097 visit:: walk_crate ( & mut late_resolution_visitor, krate) ;
2076- for ( id, span) in late_resolution_visitor. unused_labels . iter ( ) {
2098+ for ( id, span) in late_resolution_visitor. diagnostic_metadata . unused_labels . iter ( ) {
20772099 self . session . buffer_lint ( lint:: builtin:: UNUSED_LABELS , * id, * span, "unused label" ) ;
20782100 }
20792101 }
0 commit comments