@@ -735,53 +735,53 @@ fn locals_live_across_suspend_points<'tcx>(
735735 let  mut  live_locals_at_any_suspension_point = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ; 
736736
737737 for  ( block,  data)  in  body. basic_blocks . iter_enumerated ( )  { 
738-  if  let  TerminatorKind :: Yield  {  .. }  = data. terminator ( ) . kind  { 
739-  let  loc = Location  {  block,  statement_index :  data. statements . len ( )  } ; 
740- 
741-  liveness. seek_to_block_end ( block) ; 
742-  let  mut  live_locals = liveness. get ( ) . clone ( ) ; 
743- 
744-  if  !movable { 
745-  // The `liveness` variable contains the liveness of MIR locals ignoring borrows. 
746-  // This is correct for movable coroutines since borrows cannot live across 
747-  // suspension points. However for immovable coroutines we need to account for 
748-  // borrows, so we conservatively assume that all borrowed locals are live until 
749-  // we find a StorageDead statement referencing the locals. 
750-  // To do this we just union our `liveness` result with `borrowed_locals`, which 
751-  // contains all the locals which has been borrowed before this suspension point. 
752-  // If a borrow is converted to a raw reference, we must also assume that it lives 
753-  // forever. Note that the final liveness is still bounded by the storage liveness 
754-  // of the local, which happens using the `intersect` operation below. 
755-  borrowed_locals_cursor2. seek_before_primary_effect ( loc) ; 
756-  live_locals. union ( borrowed_locals_cursor2. get ( ) ) ; 
757-  } 
738+  let  TerminatorKind :: Yield  {  .. }  = data. terminator ( ) . kind  else  {  continue  } ; 
739+ 
740+  let  loc = Location  {  block,  statement_index :  data. statements . len ( )  } ; 
741+ 
742+  liveness. seek_to_block_end ( block) ; 
743+  let  mut  live_locals = liveness. get ( ) . clone ( ) ; 
744+ 
745+  if  !movable { 
746+  // The `liveness` variable contains the liveness of MIR locals ignoring borrows. 
747+  // This is correct for movable coroutines since borrows cannot live across 
748+  // suspension points. However for immovable coroutines we need to account for 
749+  // borrows, so we conservatively assume that all borrowed locals are live until 
750+  // we find a StorageDead statement referencing the locals. 
751+  // To do this we just union our `liveness` result with `borrowed_locals`, which 
752+  // contains all the locals which has been borrowed before this suspension point. 
753+  // If a borrow is converted to a raw reference, we must also assume that it lives 
754+  // forever. Note that the final liveness is still bounded by the storage liveness 
755+  // of the local, which happens using the `intersect` operation below. 
756+  borrowed_locals_cursor2. seek_before_primary_effect ( loc) ; 
757+  live_locals. union ( borrowed_locals_cursor2. get ( ) ) ; 
758+  } 
758759
759-    // Store the storage liveness for later use so we can restore the state 
760-    // after a suspension point 
761-    storage_live. seek_before_primary_effect ( loc) ; 
762-    storage_liveness_map[ block]  = Some ( storage_live. get ( ) . clone ( ) ) ; 
760+  // Store the storage liveness for later use so we can restore the state 
761+  // after a suspension point 
762+  storage_live. seek_before_primary_effect ( loc) ; 
763+  storage_liveness_map[ block]  = Some ( storage_live. get ( ) . clone ( ) ) ; 
763764
764-    // Locals live are live at this point only if they are used across 
765-    // suspension points (the `liveness` variable) 
766-    // and their storage is required (the `storage_required` variable) 
767-    requires_storage_cursor. seek_before_primary_effect ( loc) ; 
768-    live_locals. intersect ( requires_storage_cursor. get ( ) ) ; 
765+  // Locals live are live at this point only if they are used across 
766+  // suspension points (the `liveness` variable) 
767+  // and their storage is required (the `storage_required` variable) 
768+  requires_storage_cursor. seek_before_primary_effect ( loc) ; 
769+  live_locals. intersect ( requires_storage_cursor. get ( ) ) ; 
769770
770-    // The coroutine argument is ignored. 
771-    live_locals. remove ( SELF_ARG ) ; 
771+  // The coroutine argument is ignored. 
772+  live_locals. remove ( SELF_ARG ) ; 
772773
773-    debug ! ( "loc = {:?}, live_locals = {:?}" ,   loc,  live_locals) ; 
774+  debug ! ( ? loc,  ? live_locals) ; 
774775
775-    // Add the locals live at this suspension point to the set of locals which live across 
776-    // any suspension points 
777-    live_locals_at_any_suspension_point. union ( & live_locals) ; 
776+  // Add the locals live at this suspension point to the set of locals which live across 
777+  // any suspension points 
778+  live_locals_at_any_suspension_point. union ( & live_locals) ; 
778779
779-  live_locals_at_suspension_points. push ( live_locals) ; 
780-  source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ; 
781-  } 
780+  live_locals_at_suspension_points. push ( live_locals) ; 
781+  source_info_at_suspension_points. push ( data. terminator ( ) . source_info ) ; 
782782 } 
783783
784-  debug ! ( "live_locals_anywhere = {:?}" ,   live_locals_at_any_suspension_point) ; 
784+  debug ! ( ? live_locals_at_any_suspension_point) ; 
785785 let  saved_locals = CoroutineSavedLocals ( live_locals_at_any_suspension_point) ; 
786786
787787 // Renumber our liveness_map bitsets to include only the locals we are 
@@ -982,71 +982,70 @@ fn compute_layout<'tcx>(
982982 }  = liveness; 
983983
984984 // Gather live local types and their indices. 
985-  let  mut  locals = IndexVec :: < CoroutineSavedLocal ,  _ > :: new ( ) ; 
986-  let  mut  tys = IndexVec :: < CoroutineSavedLocal ,  _ > :: new ( ) ; 
987-  for  ( saved_local,  local)  in  saved_locals. iter_enumerated ( )  { 
988-  debug ! ( "coroutine saved local {:?} => {:?}" ,  saved_local,  local) ; 
989- 
990-  locals. push ( local) ; 
991-  let  decl = & body. local_decls [ local] ; 
992-  debug ! ( ?decl) ; 
993- 
994-  // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared 
995-  // the information. This is alright, since `ignore_for_traits` is only relevant when 
996-  // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer 
997-  // default. 
998-  let  ignore_for_traits = match  decl. local_info  { 
999-  // Do not include raw pointers created from accessing `static` items, as those could 
1000-  // well be re-created by another access to the same static. 
1001-  ClearCrossCrate :: Set ( box LocalInfo :: StaticRef  {  is_thread_local,  .. } )  => { 
1002-  !is_thread_local
1003-  } 
1004-  // Fake borrows are only read by fake reads, so do not have any reality in 
1005-  // post-analysis MIR. 
1006-  ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow )  => true , 
1007-  _ => false , 
1008-  } ; 
1009-  let  decl =
1010-  CoroutineSavedTy  {  ty :  decl. ty ,  source_info :  decl. source_info ,  ignore_for_traits } ; 
1011-  debug ! ( ?decl) ; 
985+  let  ( locals,  tys) :  ( IndexVec < _ ,  _ > ,  IndexVec < _ ,  _ > )  = saved_locals
986+  . iter_enumerated ( ) 
987+  . map ( |( saved_local,  local) | { 
988+  debug ! ( "coroutine saved local {saved_local:?} => {local:?}" ) ; 
1012989
1013-  tys. push ( decl) ; 
1014-  } 
990+  let  decl = & body. local_decls [ local] ; 
991+  debug ! ( ?decl) ; 
992+ 
993+  // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared 
994+  // the information. This is alright, since `ignore_for_traits` is only relevant when 
995+  // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer 
996+  // default. 
997+  let  ignore_for_traits = match  decl. local_info  { 
998+  // Do not include raw pointers created from accessing `static` items, as those could 
999+  // well be re-created by another access to the same static. 
1000+  ClearCrossCrate :: Set ( box LocalInfo :: StaticRef  {  is_thread_local,  .. } )  => { 
1001+  !is_thread_local
1002+  } 
1003+  // Fake borrows are only read by fake reads, so do not have any reality in 
1004+  // post-analysis MIR. 
1005+  ClearCrossCrate :: Set ( box LocalInfo :: FakeBorrow )  => true , 
1006+  _ => false , 
1007+  } ; 
1008+  let  decl =
1009+  CoroutineSavedTy  {  ty :  decl. ty ,  source_info :  decl. source_info ,  ignore_for_traits } ; 
1010+  debug ! ( ?decl) ; 
1011+ 
1012+  ( local,  decl) 
1013+  } ) 
1014+  . unzip ( ) ; 
10151015
10161016 // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. 
10171017 // In debuginfo, these will correspond to the beginning (UNRESUMED) or end 
10181018 // (RETURNED, POISONED) of the function. 
10191019 let  body_span = body. source_scopes [ OUTERMOST_SOURCE_SCOPE ] . span ; 
1020-  let  mut   variant_source_info:  IndexVec < VariantIdx ,  SourceInfo >  = [ 
1020+  let  variant_source_info:  IndexVec < VariantIdx ,  SourceInfo >  = [ 
10211021 SourceInfo :: outermost ( body_span. shrink_to_lo ( ) ) , 
10221022 SourceInfo :: outermost ( body_span. shrink_to_hi ( ) ) , 
10231023 SourceInfo :: outermost ( body_span. shrink_to_hi ( ) ) , 
10241024 ] 
1025-  . iter ( ) 
1026-  . copied ( ) 
1025+  . into_iter ( ) 
1026+  . chain ( source_info_at_suspension_points ) 
10271027 . collect ( ) ; 
10281028
10291029 // Build the coroutine variant field list. 
10301030 // Create a map from local indices to coroutine struct indices. 
1031-  let  mut  variant_fields:  IndexVec < VariantIdx ,  IndexVec < FieldIdx ,  CoroutineSavedLocal > >  =
1032-  iter:: repeat ( IndexVec :: new ( ) ) . take ( CoroutineArgs :: RESERVED_VARIANTS ) . collect ( ) ; 
10331031 let  mut  remap = IndexVec :: from_elem_n ( None ,  saved_locals. domain_size ( ) ) ; 
1034-  for  ( suspension_point_idx,  live_locals)  in  live_locals_at_suspension_points. iter ( ) . enumerate ( )  { 
1035-  let  variant_index =
1036-  VariantIdx :: from ( CoroutineArgs :: RESERVED_VARIANTS  + suspension_point_idx) ; 
1037-  let  mut  fields = IndexVec :: new ( ) ; 
1038-  for  ( idx,  saved_local)  in  live_locals. iter ( ) . enumerate ( )  { 
1039-  fields. push ( saved_local) ; 
1040-  // Note that if a field is included in multiple variants, we will 
1041-  // just use the first one here. That's fine; fields do not move 
1042-  // around inside coroutines, so it doesn't matter which variant 
1043-  // index we access them by. 
1044-  let  idx = FieldIdx :: from_usize ( idx) ; 
1045-  remap[ locals[ saved_local] ]  = Some ( ( tys[ saved_local] . ty ,  variant_index,  idx) ) ; 
1046-  } 
1047-  variant_fields. push ( fields) ; 
1048-  variant_source_info. push ( source_info_at_suspension_points[ suspension_point_idx] ) ; 
1049-  } 
1032+  let  variant_fields = iter:: repeat_n ( IndexVec :: new ( ) ,  CoroutineArgs :: RESERVED_VARIANTS ) 
1033+  . chain ( live_locals_at_suspension_points. into_iter ( ) . enumerate ( ) . map ( 
1034+  |( suspension_point_idx,  live_locals) | { 
1035+  let  variant_index =
1036+  VariantIdx :: from ( CoroutineArgs :: RESERVED_VARIANTS  + suspension_point_idx) ; 
1037+  let  fields = live_locals. iter ( ) . collect :: < IndexVec < FieldIdx ,  _ > > ( ) ; 
1038+  for  ( idx,  & saved_local)  in  fields. iter_enumerated ( )  { 
1039+  // Note that if a field is included in multiple variants, we will 
1040+  // just use the first one here. That's fine; fields do not move 
1041+  // around inside coroutines, so it doesn't matter which variant 
1042+  // index we access them by. 
1043+  remap[ locals[ saved_local] ]  = Some ( ( tys[ saved_local] . ty ,  variant_index,  idx) ) ; 
1044+  } 
1045+  fields
1046+  } , 
1047+  ) ) 
1048+  . collect :: < IndexVec < VariantIdx ,  _ > > ( ) ; 
10501049 debug ! ( "coroutine variant_fields = {:?}" ,  variant_fields) ; 
10511050 debug ! ( "coroutine storage_conflicts = {:#?}" ,  storage_conflicts) ; 
10521051
0 commit comments