@@ -317,19 +317,20 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
317317 // swap in a new set of IR maps for this body
318318 let mut maps = IrMaps :: new ( self . tcx ) ;
319319 let hir_id = maps. tcx . hir ( ) . body_owner ( body. id ( ) ) ;
320- let def_id = maps. tcx . hir ( ) . local_def_id ( hir_id) ;
320+ let local_def_id = maps. tcx . hir ( ) . local_def_id ( hir_id) ;
321+ let def_id = local_def_id. to_def_id ( ) ;
321322
322323 // Don't run unused pass for #[derive()]
323- if let Some ( parent) = self . tcx . parent ( def_id. to_def_id ( ) ) {
324+ if let Some ( parent) = self . tcx . parent ( def_id) {
324325 if let DefKind :: Impl = self . tcx . def_kind ( parent. expect_local ( ) ) {
325326 if self . tcx . has_attr ( parent, sym:: automatically_derived) {
326327 return ;
327328 }
328329 }
329330 }
330331
331- if let Some ( upvars ) = maps. tcx . upvars_mentioned ( def_id) {
332- for ( & var_hir_id, _upvar ) in upvars {
332+ if let Some ( captures ) = maps. tcx . typeck ( local_def_id ) . closure_captures . get ( & def_id) {
333+ for & var_hir_id in captures . keys ( ) {
333334 let var_name = maps. tcx . hir ( ) . name ( var_hir_id) ;
334335 maps. add_variable ( Upvar ( var_hir_id, var_name) ) ;
335336 }
@@ -340,7 +341,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
340341 intravisit:: walk_body ( & mut maps, body) ;
341342
342343 // compute liveness
343- let mut lsets = Liveness :: new ( & mut maps, def_id ) ;
344+ let mut lsets = Liveness :: new ( & mut maps, local_def_id ) ;
344345 let entry_ln = lsets. compute ( & body, hir_id) ;
345346 lsets. log_liveness ( entry_ln, body. id ( ) . hir_id ) ;
346347
@@ -397,10 +398,18 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
397398 // construction site.
398399 let mut call_caps = Vec :: new ( ) ;
399400 let closure_def_id = self . tcx . hir ( ) . local_def_id ( expr. hir_id ) ;
400- if let Some ( upvars) = self . tcx . upvars_mentioned ( closure_def_id) {
401- call_caps. extend ( upvars. iter ( ) . map ( |( & var_id, upvar) | {
401+ if let Some ( captures) = self
402+ . tcx
403+ . typeck ( closure_def_id)
404+ . closure_captures
405+ . get ( & closure_def_id. to_def_id ( ) )
406+ {
407+ // If closure captures is Some, upvars_mentioned must also be Some
408+ let upvars = self . tcx . upvars_mentioned ( closure_def_id) . unwrap ( ) ;
409+ call_caps. extend ( captures. keys ( ) . map ( |var_id| {
410+ let upvar = upvars[ var_id] ;
402411 let upvar_ln = self . add_live_node ( UpvarNode ( upvar. span ) ) ;
403- CaptureInfo { ln : upvar_ln, var_hid : var_id }
412+ CaptureInfo { ln : upvar_ln, var_hid : * var_id }
404413 } ) ) ;
405414 }
406415 self . set_captures ( expr. hir_id , call_caps) ;
@@ -564,6 +573,7 @@ struct Liveness<'a, 'tcx> {
564573 typeck_results : & ' a ty:: TypeckResults < ' tcx > ,
565574 param_env : ty:: ParamEnv < ' tcx > ,
566575 upvars : Option < & ' tcx FxIndexMap < hir:: HirId , hir:: Upvar > > ,
576+ closure_captures : Option < & ' tcx FxIndexMap < hir:: HirId , ty:: UpvarId > > ,
567577 successors : IndexVec < LiveNode , Option < LiveNode > > ,
568578 rwu_table : RWUTable ,
569579
@@ -587,6 +597,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
587597 let typeck_results = ir. tcx . typeck ( body_owner) ;
588598 let param_env = ir. tcx . param_env ( body_owner) ;
589599 let upvars = ir. tcx . upvars_mentioned ( body_owner) ;
600+ let closure_captures = typeck_results. closure_captures . get ( & body_owner. to_def_id ( ) ) ;
590601
591602 let closure_ln = ir. add_live_node ( ClosureNode ) ;
592603 let exit_ln = ir. add_live_node ( ExitNode ) ;
@@ -600,6 +611,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
600611 typeck_results,
601612 param_env,
602613 upvars,
614+ closure_captures,
603615 successors : IndexVec :: from_elem_n ( None , num_live_nodes) ,
604616 rwu_table : RWUTable :: new ( num_live_nodes * num_vars) ,
605617 closure_ln,
@@ -850,14 +862,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
850862 // if they are live on the entry to the closure, since only the closure
851863 // itself can access them on subsequent calls.
852864
853- if let Some ( upvars ) = self . upvars {
865+ if let Some ( closure_captures ) = self . closure_captures {
854866 // Mark upvars captured by reference as used after closure exits.
855- for ( & var_hir_id, upvar) in upvars. iter ( ) . rev ( ) {
856- let upvar_id = ty:: UpvarId {
857- var_path : ty:: UpvarPath { hir_id : var_hir_id } ,
858- closure_expr_id : self . body_owner ,
859- } ;
860- match self . typeck_results . upvar_capture ( upvar_id) {
867+ // Since closure_captures is Some, upvars must exists too.
868+ let upvars = self . upvars . unwrap ( ) ;
869+ for ( & var_hir_id, upvar_id) in closure_captures {
870+ let upvar = upvars[ & var_hir_id] ;
871+ match self . typeck_results . upvar_capture ( * upvar_id) {
861872 ty:: UpvarCapture :: ByRef ( _) => {
862873 let var = self . variable ( var_hir_id, upvar. span ) ;
863874 self . acc ( self . exit_ln , var, ACC_READ | ACC_USE ) ;
@@ -869,7 +880,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
869880
870881 let succ = self . propagate_through_expr ( & body. value , self . exit_ln ) ;
871882
872- if self . upvars . is_none ( ) {
883+ if self . closure_captures . is_none ( ) {
873884 // Either not a closure, or closure without any captured variables.
874885 // No need to determine liveness of captured variables, since there
875886 // are none.
@@ -1341,7 +1352,21 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
13411352 acc : u32 ,
13421353 ) -> LiveNode {
13431354 match path. res {
1344- Res :: Local ( hid) => self . access_var ( hir_id, hid, succ, acc, path. span ) ,
1355+ Res :: Local ( hid) => {
1356+ let in_upvars = self . upvars . map_or ( false , |u| u. contains_key ( & hid) ) ;
1357+ let in_captures = self . closure_captures . map_or ( false , |c| c. contains_key ( & hid) ) ;
1358+
1359+ match ( in_upvars, in_captures) {
1360+ ( false , _) | ( true , true ) => self . access_var ( hir_id, hid, succ, acc, path. span ) ,
1361+ ( true , false ) => {
1362+ // This case is possible when with RFC-2229, a wild pattern
1363+ // is used within a closure.
1364+ // eg: `let _ = x`. The closure doesn't capture x here,
1365+ // even though it's mentioned in the closure.
1366+ succ
1367+ }
1368+ }
1369+ }
13451370 _ => succ,
13461371 }
13471372 }
@@ -1531,11 +1556,15 @@ impl<'tcx> Liveness<'_, 'tcx> {
15311556 }
15321557
15331558 fn warn_about_unused_upvars ( & self , entry_ln : LiveNode ) {
1534- let upvars = match self . upvars {
1559+ let closure_captures = match self . closure_captures {
15351560 None => return ,
1536- Some ( upvars ) => upvars ,
1561+ Some ( closure_captures ) => closure_captures ,
15371562 } ;
1538- for ( & var_hir_id, upvar) in upvars. iter ( ) {
1563+
1564+ // If closure_captures is Some(), upvars must be Some() too.
1565+ let upvars = self . upvars . unwrap ( ) ;
1566+ for & var_hir_id in closure_captures. keys ( ) {
1567+ let upvar = upvars[ & var_hir_id] ;
15391568 let var = self . variable ( var_hir_id, upvar. span ) ;
15401569 let upvar_id = ty:: UpvarId {
15411570 var_path : ty:: UpvarPath { hir_id : var_hir_id } ,
0 commit comments