Do not renumber resume local.

This commit is contained in:
Camille Gillot 2025-09-14 15:15:49 +00:00
parent 40d879a47f
commit fe3a784ef2
13 changed files with 228 additions and 252 deletions

View file

@ -1340,14 +1340,13 @@ fn create_cases<'tcx>(
}
}
if operation == Operation::Resume {
if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() {
// Move the resume argument to the destination place of the `Yield` terminator
let resume_arg = CTX_ARG;
statements.push(Statement::new(
source_info,
StatementKind::Assign(Box::new((
point.resume_arg,
Rvalue::Use(Operand::Move(resume_arg.into())),
Rvalue::Use(Operand::Move(CTX_ARG.into())),
))),
));
}
@ -1439,7 +1438,10 @@ fn check_field_tys_sized<'tcx>(
}
impl<'tcx> crate::MirPass<'tcx> for StateTransform {
#[instrument(level = "debug", skip(self, tcx, body), ret)]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!(def_id = ?body.source.def_id());
let Some(old_yield_ty) = body.yield_ty() else {
// This only applies to coroutines
return;
@ -1518,31 +1520,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
cleanup_async_drops(body);
}
// We also replace the resume argument and insert an `Assign`.
// This is needed because the resume argument `_2` might be live across a `yield`, in which
// case there is no `Assign` to it that the transform can turn into a store to the coroutine
// state. After the yield the slot in the coroutine state would then be uninitialized.
let resume_local = CTX_ARG;
let resume_ty = body.local_decls[resume_local].ty;
let old_resume_local = replace_local(resume_local, resume_ty, body, tcx);
// When first entering the coroutine, move the resume argument into its old local
// (which is now a generator interior).
let source_info = SourceInfo::outermost(body.span);
let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
stmts.insert(
0,
Statement::new(
source_info,
StatementKind::Assign(Box::new((
old_resume_local.into(),
Rvalue::Use(Operand::Move(resume_local.into())),
))),
),
);
let always_live_locals = always_storage_live_locals(body);
let movable = coroutine_kind.movability() == hir::Movability::Movable;
let liveness_info =
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
@ -1583,6 +1561,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
};
transform.visit_body(body);
// 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.
let source_info = SourceInfo::outermost(body.span);
let args_iter = body.args_iter();
body.basic_blocks.as_mut()[START_BLOCK].statements.splice(
0..0,
args_iter.filter_map(|local| {
let (ty, variant_index, idx) = transform.remap[local]?;
let lhs = transform.make_field(variant_index, idx, ty);
let rhs = Rvalue::Use(Operand::Move(local.into()));
let assign = StatementKind::Assign(Box::new((lhs, rhs)));
Some(Statement::new(source_info, assign))
}),
);
// Update our MIR struct to reflect the changes we've made
body.arg_count = 2; // self, resume arg
body.spread_arg = None;

View file

@ -1,7 +1,7 @@
// MIR for `a::{closure#0}` 0 coroutine_drop_async
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _19;
debug _task_context => _2;
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
let mut _0: std::task::Poll<()>;
let _3: T;
@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
let mut _16: &mut impl std::future::Future<Output = ()>;
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _18: isize;
let mut _19: &mut std::task::Context<'_>;
let mut _20: u32;
let mut _19: u32;
scope 1 {
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
}
bb0: {
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _20) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
_19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14];
}
bb1: {

View file

@ -1,7 +1,7 @@
// MIR for `a::{closure#0}` 0 coroutine_drop_async
fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _19;
debug _task_context => _2;
debug x => ((*(_1.0: &mut {async fn body of a<T>()})).0: T);
let mut _0: std::task::Poll<()>;
let _3: T;
@ -20,15 +20,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a<T>()}>, _2: &mut Context<'_>)
let mut _16: &mut impl std::future::Future<Output = ()>;
let mut _17: std::pin::Pin<&mut impl std::future::Future<Output = ()>>;
let mut _18: isize;
let mut _19: &mut std::task::Context<'_>;
let mut _20: u32;
let mut _19: u32;
scope 1 {
debug x => (((*(_1.0: &mut {async fn body of a<T>()})) as variant#4).0: T);
}
bb0: {
_20 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _20) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
_19 = discriminant((*(_1.0: &mut {async fn body of a<T>()})));
switchInt(move _19) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19];
}
bb1: {

View file

@ -10,19 +10,17 @@
} */
fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _4;
debug _task_context => _2;
let mut _0: std::task::Poll<()>;
let mut _3: ();
let mut _4: &mut std::task::Context<'_>;
let mut _5: u32;
let mut _4: u32;
bb0: {
_5 = discriminant((*(_1.0: &mut {async fn body of a()})));
switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5];
_4 = discriminant((*(_1.0: &mut {async fn body of a()})));
switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5];
}
bb1: {
_4 = move _2;
_3 = const ();
goto -> bb3;
}

View file

@ -50,7 +50,7 @@
} */
fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
debug _task_context => _38;
debug _task_context => _2;
let mut _0: std::task::Poll<()>;
let _3: ();
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<'_>) ->
let mut _35: &mut std::task::Context<'_>;
let mut _36: ();
let mut _37: ();
let mut _38: &mut std::task::Context<'_>;
let mut _39: u32;
let mut _38: u32;
scope 1 {
debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
let _17: ();
@ -103,12 +102,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
}
bb0: {
_39 = discriminant((*(_1.0: &mut {async fn body of b()})));
switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
_38 = discriminant((*(_1.0: &mut {async fn body of b()})));
switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
}
bb1: {
_38 = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
@ -143,7 +141,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
StorageLive(_13);
StorageLive(_14);
StorageLive(_15);
_15 = copy _38;
_15 = copy _2;
_14 = move _15;
goto -> bb6;
}
@ -198,7 +196,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
bb11: {
StorageDead(_20);
_38 = move _19;
_2 = move _19;
StorageDead(_19);
_7 = const ();
goto -> bb4;
@ -245,7 +243,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
StorageLive(_29);
StorageLive(_30);
StorageLive(_31);
_31 = copy _38;
_31 = copy _2;
_30 = move _31;
goto -> bb18;
}
@ -295,7 +293,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) ->
bb22: {
StorageDead(_36);
_38 = move _35;
_2 = move _35;
StorageDead(_35);
_7 = const ();
goto -> bb16;

View file

@ -4,7 +4,7 @@
_s0: CoroutineSavedTy {
ty: std::string::String,
source_info: SourceInfo {
span: $DIR/coroutine.rs:17:32: 17:35 (#0),
span: $DIR/coroutine.rs:18:6: 18:9 (#0),
scope: scope[0],
},
ignore_for_traits: false,
@ -22,8 +22,8 @@
},
} */
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44})) as variant#4).0: std::string::String);
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18})) as variant#4).0: std::string::String);
let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
let _3: std::string::String;
let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
@ -39,32 +39,31 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
let mut _14: &std::panic::Location<'_>;
let _15: &std::panic::Location<'_>;
let mut _16: ();
let _17: std::string::String;
let mut _18: u32;
let mut _19: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _26: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _17: u32;
let mut _18: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _19: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
bb0: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_18 = discriminant((*_19));
switchInt(move _18) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
_18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_17 = discriminant((*_18));
switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
(((*_20) as variant#4).0: std::string::String) = move _2;
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
(((*_19) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_6 = &(((*_21) as variant#4).0: std::string::String);
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_6 = &(((*_20) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
@ -85,8 +84,8 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
StorageDead(_3);
StorageDead(_4);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_22)) = 3;
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_21)) = 3;
return;
}
@ -109,8 +108,8 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_13 = &(((*_23) as variant#4).0: std::string::String);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_13 = &(((*_22) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
@ -136,8 +135,8 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
StorageDead(_9);
StorageDead(_11);
StorageDead(_15);
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_24)) = 4;
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_23)) = 4;
return;
}
@ -155,8 +154,8 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
drop((((*_25) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
bb14: {
@ -165,8 +164,8 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:17:31: 17:44}>, _
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_26 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_26)) = 1;
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_25)) = 1;
return;
}

View file

@ -4,7 +4,7 @@
_s0: CoroutineSavedTy {
ty: std::string::String,
source_info: SourceInfo {
span: $DIR/coroutine.rs:22:54: 22:57 (#0),
span: $DIR/coroutine.rs:25:6: 25:9 (#0),
scope: scope[0],
},
ignore_for_traits: false,
@ -22,8 +22,8 @@
},
} */
fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66})) as variant#4).0: std::string::String);
fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18})) as variant#4).0: std::string::String);
let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>;
let _3: std::string::String;
let mut _4: (&str, std::string::String, &std::panic::Location<'_>);
@ -39,32 +39,31 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
let mut _14: &std::panic::Location<'_>;
let _15: &std::panic::Location<'_>;
let mut _16: ();
let _17: std::string::String;
let mut _18: u32;
let mut _19: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _26: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _17: u32;
let mut _18: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _19: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
bb0: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_18 = discriminant((*_19));
switchInt(move _18) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
_18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_17 = discriminant((*_18));
switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
(((*_20) as variant#4).0: std::string::String) = move _2;
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
(((*_19) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_6 = &(((*_21) as variant#4).0: std::string::String);
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_6 = &(((*_20) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
@ -85,8 +84,8 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
StorageDead(_3);
StorageDead(_4);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_22)) = 3;
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_21)) = 3;
return;
}
@ -109,8 +108,8 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_13 = &(((*_23) as variant#4).0: std::string::String);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_13 = &(((*_22) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
@ -136,8 +135,8 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
StorageDead(_9);
StorageDead(_11);
StorageDead(_15);
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_24)) = 4;
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_23)) = 4;
return;
}
@ -155,8 +154,8 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
drop((((*_25) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
bb14: {
@ -165,8 +164,8 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:22:53: 22:66}>, _
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_26 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_26)) = 1;
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_25)) = 1;
return;
}

View file

@ -8,18 +8,21 @@
#![feature(coroutines)]
use std::ops::{Coroutine, CoroutineState};
use std::pin::Pin;
use std::panic::Location;
use std::pin::Pin;
// EMIT_MIR coroutine.main-{closure#0}.StateTransform.after.mir
// EMIT_MIR coroutine.main-{closure#1}.StateTransform.after.mir
fn main() {
let simple = #[coroutine] |arg: String| {
let simple = #[coroutine]
|arg: String| {
yield ("first", arg.clone(), Location::caller());
yield ("second", arg.clone(), Location::caller());
};
let track_caller = #[track_caller] #[coroutine] |arg: String| {
let track_caller = #[track_caller]
#[coroutine]
|arg: String| {
yield ("first", arg.clone(), Location::caller());
yield ("second", arg.clone(), Location::caller());
};

View file

@ -7,15 +7,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12
let _4: ();
let mut _5: ();
let mut _6: ();
let mut _7: ();
let mut _8: u32;
let mut _7: u32;
scope 1 {
debug _s => (((*_1) as variant#3).0: std::string::String);
}
bb0: {
_8 = discriminant((*_1));
switchInt(move _8) -> [0: bb5, 3: bb8, otherwise: bb9];
_7 = discriminant((*_1));
switchInt(move _7) -> [0: bb5, 3: bb8, otherwise: bb9];
}
bb1: {

View file

@ -7,15 +7,14 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12
let _4: ();
let mut _5: ();
let mut _6: ();
let mut _7: ();
let mut _8: u32;
let mut _7: u32;
scope 1 {
debug _s => (((*_1) as variant#3).0: std::string::String);
}
bb0: {
_8 = discriminant((*_1));
switchInt(move _8) -> [0: bb7, 3: bb10, otherwise: bb11];
_7 = discriminant((*_1));
switchInt(move _7) -> [0: bb7, 3: bb10, otherwise: bb11];
}
bb1: {

View file

@ -22,7 +22,7 @@
} */
fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> {
debug _x => _10;
debug _x => _2;
let mut _0: std::ops::CoroutineState<(), ()>;
let _3: HasDrop;
let mut _4: !;
@ -31,19 +31,17 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}
let mut _7: ();
let _8: ();
let mut _9: ();
let _10: u8;
let mut _11: u32;
let mut _10: u32;
scope 1 {
debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop);
}
bb0: {
_11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6];
_10 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})));
switchInt(move _10) -> [0: bb1, 3: bb5, otherwise: bb6];
}
bb1: {
_10 = move _2;
nop;
(((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop;
StorageLive(_4);

View file

@ -39,8 +39,8 @@
+ let mut _28: &mut std::task::Context<'_>;
+ let mut _29: ();
+ let mut _30: ();
+ let mut _31: &mut std::task::Context<'_>;
+ let mut _32: u32;
+ let mut _31: u32;
+ let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
@ -48,7 +48,6 @@
+ let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ scope 7 {
+ let mut _15: std::future::Ready<()>;
+ scope 8 {
@ -58,14 +57,14 @@
+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
+ let mut _42: ();
+ let mut _43: std::option::Option<()>;
+ let mut _44: &mut std::option::Option<()>;
+ let mut _45: &mut std::future::Ready<()>;
+ let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ let mut _41: ();
+ let mut _42: std::option::Option<()>;
+ let mut _43: &mut std::option::Option<()>;
+ let mut _44: &mut std::future::Ready<()>;
+ let mut _45: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
+ let mut _47: &mut &mut std::future::Ready<()>;
+ let mut _46: &mut &mut std::future::Ready<()>;
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@ -75,22 +74,22 @@
+ }
+ }
+ scope 19 (inlined Option::<()>::take) {
+ let mut _48: std::option::Option<()>;
+ let mut _47: std::option::Option<()>;
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
+ scope 21 {
+ }
+ }
+ }
+ scope 22 (inlined #[track_caller] Option::<()>::expect) {
+ let mut _49: isize;
+ let mut _50: !;
+ let mut _48: isize;
+ let mut _49: !;
+ scope 23 {
+ }
+ }
+ }
+ }
+ scope 10 (inlined ready::<()>) {
+ let mut _41: std::option::Option<()>;
+ let mut _40: std::option::Option<()>;
+ }
+ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
+ }
@ -145,10 +144,9 @@
+ StorageLive(_37);
+ StorageLive(_38);
+ StorageLive(_39);
+ StorageLive(_40);
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _32 = discriminant((*_33));
+ switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
+ _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _31 = discriminant((*_32));
+ switchInt(move _31) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
}
- bb3: {
@ -158,7 +156,6 @@
+ }
+
+ bb2: {
+ StorageDead(_40);
+ StorageDead(_39);
+ StorageDead(_38);
+ StorageDead(_37);
@ -186,23 +183,22 @@
}
+ bb3: {
+ _31 = move _9;
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
+ StorageLive(_12);
+ StorageLive(_13);
+ StorageLive(_14);
+ _14 = ();
+ StorageLive(_41);
+ _41 = Option::<()>::Some(copy _14);
+ _13 = std::future::Ready::<()>(move _41);
+ StorageDead(_41);
+ StorageLive(_40);
+ _40 = Option::<()>::Some(copy _14);
+ _13 = std::future::Ready::<()>(move _40);
+ StorageDead(_40);
+ StorageDead(_14);
+ _12 = move _13;
+ StorageDead(_13);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
+ goto -> bb4;
+ }
+
@ -214,39 +210,39 @@
+ StorageLive(_19);
+ StorageLive(_20);
+ StorageLive(_21);
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
+ StorageDead(_20);
+ StorageLive(_22);
+ StorageLive(_23);
+ StorageLive(_24);
+ _24 = copy _31;
+ _24 = copy _9;
+ _23 = move _24;
+ _22 = &mut (*_23);
+ StorageDead(_24);
+ StorageLive(_44);
+ StorageLive(_45);
+ StorageLive(_46);
+ StorageLive(_50);
+ StorageLive(_49);
+ StorageLive(_41);
+ StorageLive(_42);
+ StorageLive(_43);
+ StorageLive(_44);
+ _46 = &mut _19;
+ _45 = &mut _19;
+ StorageLive(_46);
+ _46 = &mut (_19.0: &mut std::future::Ready<()>);
+ _44 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_46);
+ _43 = &mut ((*_44).0: std::option::Option<()>);
+ StorageLive(_47);
+ _47 = &mut (_19.0: &mut std::future::Ready<()>);
+ _45 = copy (_19.0: &mut std::future::Ready<()>);
+ _47 = Option::<()>::None;
+ _42 = copy ((*_44).0: std::option::Option<()>);
+ ((*_44).0: std::option::Option<()>) = copy _47;
+ StorageDead(_47);
+ _44 = &mut ((*_45).0: std::option::Option<()>);
+ StorageDead(_43);
+ StorageLive(_48);
+ _48 = Option::<()>::None;
+ _43 = copy ((*_45).0: std::option::Option<()>);
+ ((*_45).0: std::option::Option<()>) = copy _48;
+ StorageDead(_48);
+ StorageDead(_44);
+ StorageLive(_49);
+ _49 = discriminant(_43);
+ switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5];
+ _48 = discriminant(_42);
+ switchInt(move _48) -> [0: bb11, 1: bb12, otherwise: bb5];
}
+
+ bb5: {
@ -266,8 +262,8 @@
+ StorageDead(_12);
+ StorageDead(_28);
+ StorageDead(_29);
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_38)) = 3;
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_37)) = 3;
+ goto -> bb2;
+ }
+
@ -281,14 +277,14 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
+ }
+
+ bb8: {
+ _7 = Poll::<()>::Ready(move _30);
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_40)) = 1;
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_39)) = 1;
+ goto -> bb2;
+ }
+
@ -298,7 +294,7 @@
+ StorageLive(_29);
+ _28 = move _9;
+ StorageDead(_29);
+ _31 = move _28;
+ _9 = move _28;
+ StorageDead(_28);
+ _16 = const ();
+ goto -> bb4;
@ -309,18 +305,18 @@
+ }
+
+ bb11: {
+ _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
+ _49 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable;
+ }
+
+ bb12: {
+ _42 = move ((_43 as Some).0: ());
+ StorageDead(_49);
+ StorageDead(_43);
+ _18 = Poll::<()>::Ready(move _42);
+ _41 = move ((_42 as Some).0: ());
+ StorageDead(_48);
+ StorageDead(_42);
+ StorageDead(_50);
+ StorageDead(_46);
+ _18 = Poll::<()>::Ready(move _41);
+ StorageDead(_41);
+ StorageDead(_49);
+ StorageDead(_45);
+ StorageDead(_44);
+ StorageDead(_22);
+ StorageDead(_19);
+ _25 = discriminant(_18);

View file

@ -39,8 +39,8 @@
+ let mut _28: &mut std::task::Context<'_>;
+ let mut _29: ();
+ let mut _30: ();
+ let mut _31: &mut std::task::Context<'_>;
+ let mut _32: u32;
+ let mut _31: u32;
+ let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
@ -50,7 +50,6 @@
+ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
+ scope 7 {
+ let mut _15: std::future::Ready<()>;
+ scope 8 {
@ -60,14 +59,14 @@
+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 13 (inlined <std::future::Ready<()> as Future>::poll) {
+ let mut _44: ();
+ let mut _45: std::option::Option<()>;
+ let mut _46: &mut std::option::Option<()>;
+ let mut _47: &mut std::future::Ready<()>;
+ let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ let mut _43: ();
+ let mut _44: std::option::Option<()>;
+ let mut _45: &mut std::option::Option<()>;
+ let mut _46: &mut std::future::Ready<()>;
+ let mut _47: &mut std::pin::Pin<&mut std::future::Ready<()>>;
+ scope 14 (inlined <Pin<&mut std::future::Ready<()>> as DerefMut>::deref_mut) {
+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) {
+ let mut _49: &mut &mut std::future::Ready<()>;
+ let mut _48: &mut &mut std::future::Ready<()>;
+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) {
+ }
+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) {
@ -77,22 +76,22 @@
+ }
+ }
+ scope 19 (inlined Option::<()>::take) {
+ let mut _50: std::option::Option<()>;
+ let mut _49: std::option::Option<()>;
+ scope 20 (inlined std::mem::replace::<Option<()>>) {
+ scope 21 {
+ }
+ }
+ }
+ scope 22 (inlined #[track_caller] Option::<()>::expect) {
+ let mut _51: isize;
+ let mut _52: !;
+ let mut _50: isize;
+ let mut _51: !;
+ scope 23 {
+ }
+ }
+ }
+ }
+ scope 10 (inlined ready::<()>) {
+ let mut _43: std::option::Option<()>;
+ let mut _42: std::option::Option<()>;
+ }
+ scope 11 (inlined <std::future::Ready<()> as IntoFuture>::into_future) {
+ }
@ -149,10 +148,9 @@
+ StorageLive(_39);
+ StorageLive(_40);
+ StorageLive(_41);
+ StorageLive(_42);
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _32 = discriminant((*_33));
+ switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
+ _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _31 = discriminant((*_32));
+ switchInt(move _31) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
}
- bb3: {
@ -170,7 +168,6 @@
+ }
+
+ bb4: {
+ StorageDead(_42);
+ StorageDead(_41);
+ StorageDead(_40);
+ StorageDead(_39);
@ -203,23 +200,22 @@
- StorageDead(_2);
- return;
+ bb5: {
+ _31 = move _9;
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
+ StorageLive(_12);
+ StorageLive(_13);
+ StorageLive(_14);
+ _14 = ();
+ StorageLive(_43);
+ _43 = Option::<()>::Some(copy _14);
+ _13 = std::future::Ready::<()>(move _43);
+ StorageDead(_43);
+ StorageLive(_42);
+ _42 = Option::<()>::Some(copy _14);
+ _13 = std::future::Ready::<()>(move _42);
+ StorageDead(_42);
+ StorageDead(_14);
+ _12 = move _13;
+ StorageDead(_13);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
+ goto -> bb6;
}
@ -231,39 +227,39 @@
+ StorageLive(_19);
+ StorageLive(_20);
+ StorageLive(_21);
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
+ StorageDead(_20);
+ StorageLive(_22);
+ StorageLive(_23);
+ StorageLive(_24);
+ _24 = copy _31;
+ _24 = copy _9;
+ _23 = move _24;
+ _22 = &mut (*_23);
+ StorageDead(_24);
+ StorageLive(_46);
+ StorageLive(_47);
+ StorageLive(_48);
+ StorageLive(_52);
+ StorageLive(_51);
+ StorageLive(_43);
+ StorageLive(_44);
+ StorageLive(_45);
+ StorageLive(_46);
+ _48 = &mut _19;
+ _47 = &mut _19;
+ StorageLive(_48);
+ _48 = &mut (_19.0: &mut std::future::Ready<()>);
+ _46 = copy (_19.0: &mut std::future::Ready<()>);
+ StorageDead(_48);
+ _45 = &mut ((*_46).0: std::option::Option<()>);
+ StorageLive(_49);
+ _49 = &mut (_19.0: &mut std::future::Ready<()>);
+ _47 = copy (_19.0: &mut std::future::Ready<()>);
+ _49 = Option::<()>::None;
+ _44 = copy ((*_46).0: std::option::Option<()>);
+ ((*_46).0: std::option::Option<()>) = copy _49;
+ StorageDead(_49);
+ _46 = &mut ((*_47).0: std::option::Option<()>);
+ StorageDead(_45);
+ StorageLive(_50);
+ _50 = Option::<()>::None;
+ _45 = copy ((*_47).0: std::option::Option<()>);
+ ((*_47).0: std::option::Option<()>) = copy _50;
+ StorageDead(_50);
+ StorageDead(_46);
+ StorageLive(_51);
+ _51 = discriminant(_45);
+ switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7];
+ _50 = discriminant(_44);
+ switchInt(move _50) -> [0: bb16, 1: bb17, otherwise: bb7];
}
- bb6 (cleanup): {
@ -285,8 +281,8 @@
+ StorageDead(_12);
+ StorageDead(_28);
+ StorageDead(_29);
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_38)) = 3;
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_37)) = 3;
+ goto -> bb4;
+ }
+
@ -300,14 +296,14 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
+ }
+
+ bb10: {
+ _7 = Poll::<()>::Ready(move _30);
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_40)) = 1;
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_39)) = 1;
+ goto -> bb4;
+ }
+
@ -319,13 +315,13 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
+ }
+
+ bb12 (cleanup): {
+ _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_42)) = 2;
+ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_41)) = 2;
+ goto -> bb2;
+ }
+
@ -335,7 +331,7 @@
+ StorageLive(_29);
+ _28 = move _9;
+ StorageDead(_29);
+ _31 = move _28;
+ _9 = move _28;
+ StorageDead(_28);
+ _16 = const ();
+ goto -> bb6;
@ -350,18 +346,18 @@
+ }
+
+ bb16: {
+ _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
+ _51 = option::expect_failed(const "`Ready` polled after completion") -> bb11;
+ }
+
+ bb17: {
+ _44 = move ((_45 as Some).0: ());
+ StorageDead(_51);
+ StorageDead(_45);
+ _18 = Poll::<()>::Ready(move _44);
+ _43 = move ((_44 as Some).0: ());
+ StorageDead(_50);
+ StorageDead(_44);
+ StorageDead(_52);
+ StorageDead(_48);
+ _18 = Poll::<()>::Ready(move _43);
+ StorageDead(_43);
+ StorageDead(_51);
+ StorageDead(_47);
+ StorageDead(_46);
+ StorageDead(_22);
+ StorageDead(_19);
+ _25 = discriminant(_18);