@@ -794,13 +794,11 @@ fn compute_layout<'tcx>(
794794 // (RETURNED, POISONED) of the function.
795795 const RESERVED_VARIANTS : usize = 3 ;
796796 let body_span = body. source_scopes [ OUTERMOST_SOURCE_SCOPE ] . span ;
797- let mut variant_source_info: IndexVec < VariantIdx , SourceInfo > = [
797+ let mut variant_source_info: IndexVec < VariantIdx , SourceInfo > = std :: array :: IntoIter :: new ( [
798798 SourceInfo :: outermost ( body_span. shrink_to_lo ( ) ) ,
799799 SourceInfo :: outermost ( body_span. shrink_to_hi ( ) ) ,
800800 SourceInfo :: outermost ( body_span. shrink_to_hi ( ) ) ,
801- ]
802- . iter ( )
803- . copied ( )
801+ ] )
804802 . collect ( ) ;
805803
806804 // Build the generator variant field list.
@@ -1258,7 +1256,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12581256 ty:: Generator ( _, substs, movability) => {
12591257 let substs = substs. as_generator ( ) ;
12601258 (
1261- substs. upvar_tys ( ) . collect ( ) ,
1259+ substs. upvar_tys ( ) . collect :: < Vec < _ > > ( ) ,
12621260 substs. witness ( ) ,
12631261 substs. discr_ty ( tcx) ,
12641262 movability == hir:: Movability :: Movable ,
@@ -1291,8 +1289,21 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
12911289
12921290 // When first entering the generator, move the resume argument into its new local.
12931291 let source_info = SourceInfo :: outermost ( body. span ) ;
1294- let stmts = & mut body. basic_blocks_mut ( ) [ BasicBlock :: new ( 0 ) ] . statements ;
1295- stmts. insert (
1292+
1293+ let mut upvar_collector = ExtractGeneratorUpvarLocals :: default ( ) ;
1294+ for ( block, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
1295+ upvar_collector. visit_basic_block_data ( block, data) ;
1296+ }
1297+ let upvar_locals = upvar_collector. finish ( ) ;
1298+ tracing:: info!( "Upvar locals: {:?}" , upvar_locals) ;
1299+ tracing:: info!( "Upvar count: {:?}" , upvars. len( ) ) ;
1300+ if upvar_locals. len ( ) != upvars. len ( ) {
1301+ eprintln ! ( "{:#?}" , body) ;
1302+ assert_eq ! ( upvar_locals. len( ) , upvars. len( ) ) ;
1303+ }
1304+
1305+ let first_block = & mut body. basic_blocks_mut ( ) [ BasicBlock :: new ( 0 ) ] ;
1306+ first_block. statements . insert (
12961307 0 ,
12971308 Statement {
12981309 source_info,
@@ -1375,6 +1386,53 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
13751386 }
13761387}
13771388
1389+ /// Finds locals that are assigned from generator upvars.
1390+ #[ derive( Default ) ]
1391+ struct ExtractGeneratorUpvarLocals {
1392+ upvar_locals : FxHashMap < Field , Vec < Local > > ,
1393+ }
1394+
1395+ impl ExtractGeneratorUpvarLocals {
1396+ fn finish ( self ) -> FxHashMap < Field , Vec < Local > > {
1397+ self . upvar_locals
1398+ }
1399+ }
1400+
1401+ impl < ' tcx > Visitor < ' tcx > for ExtractGeneratorUpvarLocals {
1402+ fn visit_assign ( & mut self , place : & Place < ' tcx > , rvalue : & Rvalue < ' tcx > , location : Location ) {
1403+ let mut visitor = FindGeneratorFieldAccess { field_index : None } ;
1404+ visitor. visit_rvalue ( rvalue, location) ;
1405+
1406+ if let Some ( field_index) = visitor. field_index {
1407+ self . upvar_locals . entry ( field_index) . or_insert_with ( || vec ! [ ] ) . push ( place. local ) ;
1408+ }
1409+ }
1410+ }
1411+
1412+ struct FindGeneratorFieldAccess {
1413+ field_index : Option < Field > ,
1414+ }
1415+
1416+ impl < ' tcx > Visitor < ' tcx > for FindGeneratorFieldAccess {
1417+ fn visit_projection (
1418+ & mut self ,
1419+ place_ref : PlaceRef < ' tcx > ,
1420+ _context : PlaceContext ,
1421+ _location : Location ,
1422+ ) {
1423+ tracing:: info!( "visit_projection, place_ref={:#?}" , place_ref) ;
1424+
1425+ if place_ref. local . as_usize ( ) == 1 {
1426+ if !place_ref. projection . is_empty ( ) {
1427+ if let Some ( ProjectionElem :: Field ( field, _) ) = place_ref. projection . get ( 0 ) {
1428+ assert ! ( self . field_index. is_none( ) ) ;
1429+ self . field_index = Some ( * field) ;
1430+ }
1431+ }
1432+ }
1433+ }
1434+ }
1435+
13781436/// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields
13791437/// in the generator state machine but whose storage is not marked as conflicting
13801438///
0 commit comments