@@ -244,6 +244,7 @@ struct LocalInfo {
244244enum VarKind {
245245 Param ( HirId , Symbol ) ,
246246 Local ( LocalInfo ) ,
247+ Upvar ( HirId , Symbol ) ,
247248}
248249
249250struct IrMaps < ' tcx > {
@@ -296,7 +297,7 @@ impl IrMaps<'tcx> {
296297 self . num_vars += 1 ;
297298
298299 match vk {
299- Local ( LocalInfo { id : node_id, .. } ) | Param ( node_id, _) => {
300+ Local ( LocalInfo { id : node_id, .. } ) | Param ( node_id, _) | Upvar ( node_id , _ ) => {
300301 self . variable_map . insert ( node_id, v) ;
301302 }
302303 }
@@ -317,14 +318,14 @@ impl IrMaps<'tcx> {
317318
318319 fn variable_name ( & self , var : Variable ) -> String {
319320 match self . var_kinds [ var. get ( ) ] {
320- Local ( LocalInfo { name, .. } ) | Param ( _, name) => name. to_string ( ) ,
321+ Local ( LocalInfo { name, .. } ) | Param ( _, name) | Upvar ( _ , name ) => name. to_string ( ) ,
321322 }
322323 }
323324
324325 fn variable_is_shorthand ( & self , var : Variable ) -> bool {
325326 match self . var_kinds [ var. get ( ) ] {
326327 Local ( LocalInfo { is_shorthand, .. } ) => is_shorthand,
327- Param ( ..) => false ,
328+ Param ( ..) | Upvar ( .. ) => false ,
328329 }
329330 }
330331
@@ -365,6 +366,14 @@ fn visit_fn<'tcx>(
365366
366367 let body = ir. tcx . hir ( ) . body ( body_id) ;
367368
369+ if let Some ( upvars) = ir. tcx . upvars_mentioned ( def_id) {
370+ for ( & var_hir_id, _upvar) in upvars {
371+ debug ! ( "adding upvar {:?}" , var_hir_id) ;
372+ let var_name = ir. tcx . hir ( ) . name ( var_hir_id) ;
373+ fn_maps. add_variable ( Upvar ( var_hir_id, var_name) ) ;
374+ }
375+ }
376+
368377 for param in body. params {
369378 let is_shorthand = match param. pat . kind {
370379 rustc_hir:: PatKind :: Struct ( ..) => true ,
@@ -450,11 +459,8 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
450459 // live nodes required for uses or definitions of variables:
451460 hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, ref path) ) => {
452461 debug ! ( "expr {}: path that leads to {:?}" , expr. hir_id, path. res) ;
453- if let Res :: Local ( var_hir_id) = path. res {
454- let upvars = ir. tcx . upvars_mentioned ( ir. body_owner ) ;
455- if !upvars. map_or ( false , |upvars| upvars. contains_key ( & var_hir_id) ) {
456- ir. add_live_node_for_node ( expr. hir_id , ExprNode ( expr. span ) ) ;
457- }
462+ if let Res :: Local ( _var_hir_id) = path. res {
463+ ir. add_live_node_for_node ( expr. hir_id , ExprNode ( expr. span ) ) ;
458464 }
459465 intravisit:: walk_expr ( ir, expr) ;
460466 }
@@ -470,16 +476,9 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
470476 let mut call_caps = Vec :: new ( ) ;
471477 let closure_def_id = ir. tcx . hir ( ) . local_def_id ( expr. hir_id ) ;
472478 if let Some ( upvars) = ir. tcx . upvars_mentioned ( closure_def_id) {
473- let parent_upvars = ir. tcx . upvars_mentioned ( ir. body_owner ) ;
474- call_caps. extend ( upvars. iter ( ) . filter_map ( |( & var_id, upvar) | {
475- let has_parent =
476- parent_upvars. map_or ( false , |upvars| upvars. contains_key ( & var_id) ) ;
477- if !has_parent {
478- let upvar_ln = ir. add_live_node ( UpvarNode ( upvar. span ) ) ;
479- Some ( CaptureInfo { ln : upvar_ln, var_hid : var_id } )
480- } else {
481- None
482- }
479+ call_caps. extend ( upvars. iter ( ) . map ( |( & var_id, upvar) | {
480+ let upvar_ln = ir. add_live_node ( UpvarNode ( upvar. span ) ) ;
481+ CaptureInfo { ln : upvar_ln, var_hid : var_id }
483482 } ) ) ;
484483 }
485484 ir. set_captures ( expr. hir_id , call_caps) ;
@@ -894,6 +893,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
894893 debug ! ( "compute: using id for body, {:?}" , body) ;
895894
896895 let s = self . s ;
896+
897+ if let Some ( upvars) = self . ir . tcx . upvars_mentioned ( self . ir . body_owner ) {
898+ for ( & var_hir_id, upvar) in upvars. iter ( ) . rev ( ) {
899+ let var = self . variable ( var_hir_id, upvar. span ) ;
900+ self . acc ( s. exit_ln , var, ACC_READ | ACC_USE ) ;
901+ }
902+ }
903+
897904 let entry_ln = self . propagate_through_expr ( body, s. exit_ln ) ;
898905
899906 // hack to skip the loop unless debug! is enabled:
@@ -1345,14 +1352,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
13451352 acc : u32 ,
13461353 ) -> LiveNode {
13471354 match path. res {
1348- Res :: Local ( hid) => {
1349- let upvars = self . ir . tcx . upvars_mentioned ( self . ir . body_owner ) ;
1350- if !upvars. map_or ( false , |upvars| upvars. contains_key ( & hid) ) {
1351- self . access_var ( hir_id, hid, succ, acc, path. span )
1352- } else {
1353- succ
1354- }
1355- }
1355+ Res :: Local ( hid) => self . access_var ( hir_id, hid, succ, acc, path. span ) ,
13561356 _ => succ,
13571357 }
13581358 }
@@ -1511,16 +1511,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
15111511 match expr. kind {
15121512 hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, ref path) ) => {
15131513 if let Res :: Local ( var_hid) = path. res {
1514- let upvars = self . ir . tcx . upvars_mentioned ( self . ir . body_owner ) ;
1515- if !upvars. map_or ( false , |upvars| upvars. contains_key ( & var_hid) ) {
1516- // Assignment to an immutable variable or argument: only legal
1517- // if there is no later assignment. If this local is actually
1518- // mutable, then check for a reassignment to flag the mutability
1519- // as being used.
1520- let ln = self . live_node ( expr. hir_id , expr. span ) ;
1521- let var = self . variable ( var_hid, expr. span ) ;
1522- self . warn_about_dead_assign ( vec ! [ expr. span] , expr. hir_id , ln, var) ;
1523- }
1514+ // Assignment to an immutable variable or argument: only legal
1515+ // if there is no later assignment. If this local is actually
1516+ // mutable, then check for a reassignment to flag the mutability
1517+ // as being used.
1518+ let ln = self . live_node ( expr. hir_id , expr. span ) ;
1519+ let var = self . variable ( var_hid, expr. span ) ;
1520+ self . warn_about_dead_assign ( vec ! [ expr. span] , expr. hir_id , ln, var) ;
15241521 }
15251522 }
15261523 _ => {
0 commit comments