@@ -244,6 +244,7 @@ struct LocalInfo {
244
244
enum VarKind {
245
245
Param ( HirId , Symbol ) ,
246
246
Local ( LocalInfo ) ,
247
+ Upvar ( HirId , Symbol ) ,
247
248
}
248
249
249
250
struct IrMaps < ' tcx > {
@@ -296,7 +297,7 @@ impl IrMaps<'tcx> {
296
297
self . num_vars += 1 ;
297
298
298
299
match vk {
299
- Local ( LocalInfo { id : node_id, .. } ) | Param ( node_id, _) => {
300
+ Local ( LocalInfo { id : node_id, .. } ) | Param ( node_id, _) | Upvar ( node_id , _ ) => {
300
301
self . variable_map . insert ( node_id, v) ;
301
302
}
302
303
}
@@ -317,14 +318,14 @@ impl IrMaps<'tcx> {
317
318
318
319
fn variable_name ( & self , var : Variable ) -> String {
319
320
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 ( ) ,
321
322
}
322
323
}
323
324
324
325
fn variable_is_shorthand ( & self , var : Variable ) -> bool {
325
326
match self . var_kinds [ var. get ( ) ] {
326
327
Local ( LocalInfo { is_shorthand, .. } ) => is_shorthand,
327
- Param ( ..) => false ,
328
+ Param ( ..) | Upvar ( .. ) => false ,
328
329
}
329
330
}
330
331
@@ -365,6 +366,14 @@ fn visit_fn<'tcx>(
365
366
366
367
let body = ir. tcx . hir ( ) . body ( body_id) ;
367
368
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
+
368
377
for param in body. params {
369
378
let is_shorthand = match param. pat . kind {
370
379
rustc_hir:: PatKind :: Struct ( ..) => true ,
@@ -450,11 +459,8 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
450
459
// live nodes required for uses or definitions of variables:
451
460
hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, ref path) ) => {
452
461
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 ) ) ;
458
464
}
459
465
intravisit:: walk_expr ( ir, expr) ;
460
466
}
@@ -470,16 +476,9 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
470
476
let mut call_caps = Vec :: new ( ) ;
471
477
let closure_def_id = ir. tcx . hir ( ) . local_def_id ( expr. hir_id ) ;
472
478
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 }
483
482
} ) ) ;
484
483
}
485
484
ir. set_captures ( expr. hir_id , call_caps) ;
@@ -894,6 +893,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
894
893
debug ! ( "compute: using id for body, {:?}" , body) ;
895
894
896
895
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
+
897
904
let entry_ln = self . propagate_through_expr ( body, s. exit_ln ) ;
898
905
899
906
// hack to skip the loop unless debug! is enabled:
@@ -1345,14 +1352,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
1345
1352
acc : u32 ,
1346
1353
) -> LiveNode {
1347
1354
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 ) ,
1356
1356
_ => succ,
1357
1357
}
1358
1358
}
@@ -1511,16 +1511,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
1511
1511
match expr. kind {
1512
1512
hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( _, ref path) ) => {
1513
1513
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) ;
1524
1521
}
1525
1522
}
1526
1523
_ => {
0 commit comments