Skip to content

Commit 833afb0

Browse files
committed
Create a visitor that maps upvar fields to corresponding MIR locals
1 parent 17dfae7 commit 833afb0

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

compiler/rustc_mir_transform/src/generator.rs

+65-7
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)