Skip to content

Commit a8dcb8b

Browse files
authored
Unrolled build for #146552
Rollup merge of #146552 - cjgillot:resume-noremap, r=jackh726 StateTransform: Do not renumber resume local. MIR parameters are not explicitly assigned-to when entering the MIR body. If we want to save their values inside the coroutine state, we need to do so explicitly. This was done by renaming the `_2` local, and introducing an explicit assignment pre-transform. This particular trick confuses me. This version makes explicit that we are assigning parameters to saved locals. r? ``@dingxiangfei2009``
2 parents ba4b643 + eddd755 commit a8dcb8b

17 files changed

+639
-225
lines changed

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl<'tcx> Body<'tcx> {
471471

472472
/// Returns an iterator over all function arguments.
473473
#[inline]
474-
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
474+
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator + use<> {
475475
(1..self.arg_count + 1).map(Local::new)
476476
}
477477

compiler/rustc_middle/src/mir/query.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
1717
rustc_index::newtype_index! {
1818
#[derive(HashStable)]
1919
#[encodable]
20-
#[debug_format = "_{}"]
20+
#[debug_format = "_s{}"]
2121
pub struct CoroutineSavedLocal {}
2222
}
2323

compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,14 +1340,13 @@ fn create_cases<'tcx>(
13401340
}
13411341
}
13421342

1343-
if operation == Operation::Resume {
1343+
if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() {
13441344
// Move the resume argument to the destination place of the `Yield` terminator
1345-
let resume_arg = CTX_ARG;
13461345
statements.push(Statement::new(
13471346
source_info,
13481347
StatementKind::Assign(Box::new((
13491348
point.resume_arg,
1350-
Rvalue::Use(Operand::Move(resume_arg.into())),
1349+
Rvalue::Use(Operand::Move(CTX_ARG.into())),
13511350
))),
13521351
));
13531352
}
@@ -1439,7 +1438,10 @@ fn check_field_tys_sized<'tcx>(
14391438
}
14401439

14411440
impl<'tcx> crate::MirPass<'tcx> for StateTransform {
1441+
#[instrument(level = "debug", skip(self, tcx, body), ret)]
14421442
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
1443+
debug!(def_id = ?body.source.def_id());
1444+
14431445
let Some(old_yield_ty) = body.yield_ty() else {
14441446
// This only applies to coroutines
14451447
return;
@@ -1518,31 +1520,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
15181520
cleanup_async_drops(body);
15191521
}
15201522

1521-
// We also replace the resume argument and insert an `Assign`.
1522-
// This is needed because the resume argument `_2` might be live across a `yield`, in which
1523-
// case there is no `Assign` to it that the transform can turn into a store to the coroutine
1524-
// state. After the yield the slot in the coroutine state would then be uninitialized.
1525-
let resume_local = CTX_ARG;
1526-
let resume_ty = body.local_decls[resume_local].ty;
1527-
let old_resume_local = replace_local(resume_local, resume_ty, body, tcx);
1528-
1529-
// When first entering the coroutine, move the resume argument into its old local
1530-
// (which is now a generator interior).
1531-
let source_info = SourceInfo::outermost(body.span);
1532-
let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
1533-
stmts.insert(
1534-
0,
1535-
Statement::new(
1536-
source_info,
1537-
StatementKind::Assign(Box::new((
1538-
old_resume_local.into(),
1539-
Rvalue::Use(Operand::Move(resume_local.into())),
1540-
))),
1541-
),
1542-
);
1543-
15441523
let always_live_locals = always_storage_live_locals(body);
1545-
15461524
let movable = coroutine_kind.movability() == hir::Movability::Movable;
15471525
let liveness_info =
15481526
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
@@ -1583,6 +1561,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
15831561
};
15841562
transform.visit_body(body);
15851563

1564+
// MIR parameters are not explicitly assigned-to when entering the MIR body.
1565+
// If we want to save their values inside the coroutine state, we need to do so explicitly.
1566+
let source_info = SourceInfo::outermost(body.span);
1567+
let args_iter = body.args_iter();
1568+
body.basic_blocks.as_mut()[START_BLOCK].statements.splice(
1569+
0..0,
1570+
args_iter.filter_map(|local| {
1571+
let (ty, variant_index, idx) = transform.remap[local]?;
1572+
let lhs = transform.make_field(variant_index, idx, ty);
1573+
let rhs = Rvalue::Use(Operand::Move(local.into()));
1574+
let assign = StatementKind::Assign(Box::new((lhs, rhs)));
1575+
Some(Statement::new(source_info, assign))
1576+
}),
1577+
);
1578+
15861579
// Update our MIR struct to reflect the changes we've made
15871580
body.arg_count = 2; // self, resume arg
15881581
body.spread_arg = None;

tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// MIR for `a::{closure#0}` 0 coroutine_drop_async
22

33
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
4-
debug _task_context => _19;
4+
debug _task_context => _2;
55
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
66
let mut _0: std::task::Poll<()>;
77
let _3: T;
@@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
2020
let mut _16: &mut impl std::future::Future<Output = ()>;
2121
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
2222
let mut _18: isize;
23-
let mut _19: &mut std::task::Context<'_>;
24-
let mut _20: u32;
23+
let mut _19: u32;
2524
scope 1 {
2625
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
2726
}
2827

2928
bb0: {
30-
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
31-
switchInt(move _20) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
29+
_19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
30+
switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
3231
}
3332

3433
bb1: {

tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// MIR for `a::{closure#0}` 0 coroutine_drop_async
22

33
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
4-
debug _task_context => _19;
4+
debug _task_context => _2;
55
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
66
let mut _0: std::task::Poll<()>;
77
let _3: T;
@@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
2020
let mut _16: &mut impl std::future::Future<Output = ()>;
2121
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
2222
let mut _18: isize;
23-
let mut _19: &mut std::task::Context<'_>;
24-
let mut _20: u32;
23+
let mut _19: u32;
2524
scope 1 {
2625
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
2726
}
2827

2928
bb0: {
30-
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
31-
switchInt(move _20) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
29+
_19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
30+
switchInt(move _19) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
3231
}
3332

3433
bb1: {

tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,17 @@
1010
} */
1111

1212
fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
13-
debug _task_context => _4;
13+
debug _task_context => _2;
1414
let mut _0: std::task::Poll<()>;
1515
let mut _3: ();
16-
let mut _4: &mut std::task::Context<'_>;
17-
let mut _5: u32;
16+
let mut _4: u32;
1817

1918
bb0: {
20-
_5 = discriminant((*(_1.0: &mut {async fn body of a()})));
21-
switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5];
19+
_4 = discriminant((*(_1.0: &mut {async fn body of a()})));
20+
switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5];
2221
}
2322

2423
bb1: {
25-
_4 = move _2;
2624
_3 = const ();
2725
goto -> bb3;
2826
}

tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// MIR for `b::{closure#0}` 0 coroutine_resume
22
/* coroutine_layout = CoroutineLayout {
33
field_tys: {
4-
_0: CoroutineSavedTy {
4+
_s0: CoroutineSavedTy {
55
ty: Coroutine(
66
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
77
[
@@ -18,7 +18,7 @@
1818
},
1919
ignore_for_traits: false,
2020
},
21-
_1: CoroutineSavedTy {
21+
_s1: CoroutineSavedTy {
2222
ty: Coroutine(
2323
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
2424
[
@@ -40,17 +40,17 @@
4040
Unresumed(0): [],
4141
Returned (1): [],
4242
Panicked (2): [],
43-
Suspend0 (3): [_0],
44-
Suspend1 (4): [_1],
43+
Suspend0 (3): [_s0],
44+
Suspend1 (4): [_s1],
4545
},
4646
storage_conflicts: BitMatrix(2x2) {
47-
(_0, _0),
48-
(_1, _1),
47+
(_s0, _s0),
48+
(_s1, _s1),
4949
},
5050
} */
5151

5252
fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
53-
debug _task_context => _38;
53+
debug _task_context => _2;
5454
let mut _0: std::task::Poll<()>;
5555
let _3: ();
5656
let mut _4: {async fn body of a()};
@@ -85,8 +85,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
8585
let mut _35: &mut std::task::Context<'_>;
8686
let mut _36: ();
8787
let mut _37: ();
88-
let mut _38: &mut std::task::Context<'_>;
89-
let mut _39: u32;
88+
let mut _38: u32;
9089
scope 1 {
9190
debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
9291
let _17: ();
@@ -103,12 +102,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
103102
}
104103

105104
bb0: {
106-
_39 = discriminant((*(_1.0: &mut {async fn body of b()})));
107-
switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
105+
_38 = discriminant((*(_1.0: &mut {async fn body of b()})));
106+
switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
108107
}
109108

110109
bb1: {
111-
_38 = move _2;
112110
StorageLive(_3);
113111
StorageLive(_4);
114112
StorageLive(_5);
@@ -143,7 +141,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
143141
StorageLive(_13);
144142
StorageLive(_14);
145143
StorageLive(_15);
146-
_15 = copy _38;
144+
_15 = copy _2;
147145
_14 = move _15;
148146
goto -> bb6;
149147
}
@@ -198,7 +196,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
198196

199197
bb11: {
200198
StorageDead(_20);
201-
_38 = move _19;
199+
_2 = move _19;
202200
StorageDead(_19);
203201
_7 = const ();
204202
goto -> bb4;
@@ -245,7 +243,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
245243
StorageLive(_29);
246244
StorageLive(_30);
247245
StorageLive(_31);
248-
_31 = copy _38;
246+
_31 = copy _2;
249247
_30 = move _31;
250248
goto -> bb18;
251249
}
@@ -295,7 +293,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
295293

296294
bb22: {
297295
StorageDead(_36);
298-
_38 = move _35;
296+
_2 = move _35;
299297
StorageDead(_35);
300298
_7 = const ();
301299
goto -> bb16;

0 commit comments

Comments
 (0)