From 76324c7fb5bf6d0a43ab14197950705607c56868 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Wed, 8 Oct 2025 19:44:41 +0000 Subject: [PATCH 1/7] Only load pin field once. --- compiler/rustc_mir_transform/src/coroutine.rs | 53 ++++--- .../rustc_mir_transform/src/coroutine/drop.rs | 7 +- ...#0}.coroutine_drop_async.0.panic-abort.mir | 14 +- ...0}.coroutine_drop_async.0.panic-unwind.mir | 16 ++- ...await.a-{closure#0}.coroutine_resume.0.mir | 6 +- ...await.b-{closure#0}.coroutine_resume.0.mir | 26 ++-- ....main-{closure#0}.StateTransform.after.mir | 30 ++-- ....main-{closure#1}.StateTransform.after.mir | 30 ++-- ...ny.main-{closure#0}.coroutine_resume.0.mir | 10 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 120 ++++++---------- ....run2-{closure#0}.Inline.panic-unwind.diff | 134 +++++++----------- .../async-closure.stdout | 20 +-- 12 files changed, 196 insertions(+), 270 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 26b6003e1095e..4094ad470770a 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -132,8 +132,8 @@ struct SelfArgVisitor<'tcx> { } impl<'tcx> SelfArgVisitor<'tcx> { - fn new(tcx: TyCtxt<'tcx>, elem: ProjectionElem>) -> Self { - Self { tcx, new_base: Place { local: SELF_ARG, projection: tcx.mk_place_elems(&[elem]) } } + fn new(tcx: TyCtxt<'tcx>, new_base: Place<'tcx>) -> Self { + Self { tcx, new_base } } } @@ -146,16 +146,14 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> { assert_ne!(*local, SELF_ARG); } - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, _: Location) { if place.local == SELF_ARG { replace_base(place, self.new_base, self.tcx); - } else { - self.visit_local(&mut place.local, context, location); + } - for elem in place.projection.iter() { - if let PlaceElem::Index(local) = elem { - assert_ne!(local, SELF_ARG); - } + for elem in place.projection.iter() { + if let PlaceElem::Index(local) = elem { + assert_ne!(local, SELF_ARG); } } } @@ -520,20 +518,22 @@ fn make_aggregate_adt<'tcx>( #[tracing::instrument(level = "trace", skip(tcx, body))] fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let coroutine_ty = body.local_decls.raw[1].ty; + let coroutine_ty = body.local_decls[SELF_ARG].ty; let ref_coroutine_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty); // Replace the by value coroutine argument - body.local_decls.raw[1].ty = ref_coroutine_ty; + body.local_decls[SELF_ARG].ty = ref_coroutine_ty; // Add a deref to accesses of the coroutine state - SelfArgVisitor::new(tcx, ProjectionElem::Deref).visit_body(body); + SelfArgVisitor::new(tcx, tcx.mk_place_deref(SELF_ARG.into())).visit_body(body); } #[tracing::instrument(level = "trace", skip(tcx, body))] fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let ref_coroutine_ty = body.local_decls.raw[1].ty; + let coroutine_ty = body.local_decls[SELF_ARG].ty; + + let ref_coroutine_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty); let pin_did = tcx.require_lang_item(LangItem::Pin, body.span); let pin_adt_ref = tcx.adt_def(pin_did); @@ -541,11 +541,26 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let pin_ref_coroutine_ty = Ty::new_adt(tcx, pin_adt_ref, args); // Replace the by ref coroutine argument - body.local_decls.raw[1].ty = pin_ref_coroutine_ty; + body.local_decls[SELF_ARG].ty = pin_ref_coroutine_ty; + + let unpinned_local = body.local_decls.push(LocalDecl::new(ref_coroutine_ty, body.span)); // Add the Pin field access to accesses of the coroutine state - SelfArgVisitor::new(tcx, ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty)) - .visit_body(body); + SelfArgVisitor::new(tcx, tcx.mk_place_deref(unpinned_local.into())).visit_body(body); + + let source_info = SourceInfo::outermost(body.span); + let pin_field = tcx.mk_place_field(SELF_ARG.into(), FieldIdx::ZERO, ref_coroutine_ty); + + body.basic_blocks_mut()[START_BLOCK].statements.insert( + 0, + Statement::new( + source_info, + StatementKind::Assign(Box::new(( + unpinned_local.into(), + Rvalue::Use(Operand::Copy(pin_field)), + ))), + ), + ); } /// Transforms the `body` of the coroutine applying the following transforms: @@ -1297,8 +1312,6 @@ fn create_coroutine_resume_function<'tcx>( let default_block = insert_term_block(body, TerminatorKind::Unreachable); insert_switch(body, cases, &transform, default_block); - make_coroutine_state_argument_indirect(tcx, body); - match transform.coroutine_kind { CoroutineKind::Coroutine(_) | CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) => @@ -1307,7 +1320,9 @@ fn create_coroutine_resume_function<'tcx>( } // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. - CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {} + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { + make_coroutine_state_argument_indirect(tcx, body); + } } // Make sure we remove dead blocks to remove diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 41c588f0d8d31..2699a051a8fea 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -684,12 +684,13 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(poll_enum, source_info); - make_coroutine_state_argument_indirect(tcx, &mut body); - match transform.coroutine_kind { // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. - CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {} + CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { + make_coroutine_state_argument_indirect(tcx, &mut body); + } + _ => { make_coroutine_state_argument_pinned(tcx, &mut body); } diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir index 541b9b9895b3c..435c1532895ca 100644 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -2,7 +2,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _2; - debug x => ((*(_1.0: &mut {async fn body of a()})).0: T); + debug x => ((*_20).0: T); let mut _0: std::task::Poll<()>; let _3: T; let mut _4: impl std::future::Future; @@ -21,12 +21,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) let mut _17: isize; let mut _18: (); let mut _19: u32; + let mut _20: &mut {async fn body of a()}; scope 1 { - debug x => (((*(_1.0: &mut {async fn body of a()})) as variant#4).0: T); + debug x => (((*_20) as variant#4).0: T); } bb0: { - _19 = discriminant((*(_1.0: &mut {async fn body of a()}))); + _20 = copy (_1.0: &mut {async fn body of a()}); + _19 = discriminant((*_20)); switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14]; } @@ -43,13 +45,13 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) bb3: { _0 = Poll::<()>::Pending; - discriminant((*(_1.0: &mut {async fn body of a()}))) = 4; + discriminant((*_20)) = 4; return; } bb4: { StorageLive(_16); - _15 = &mut (((*(_1.0: &mut {async fn body of a()})) as variant#4).1: impl std::future::Future); + _15 = &mut (((*_20) as variant#4).1: impl std::future::Future); _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb7, unwind unreachable]; } @@ -81,7 +83,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb11: { - drop(((*(_1.0: &mut {async fn body of a()})).0: T)) -> [return: bb10, unwind unreachable]; + drop(((*_20).0: T)) -> [return: bb10, unwind unreachable]; } bb12: { diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir index f2e1fb0997568..1dc1d08136290 100644 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -2,7 +2,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { debug _task_context => _2; - debug x => ((*(_1.0: &mut {async fn body of a()})).0: T); + debug x => ((*_20).0: T); let mut _0: std::task::Poll<()>; let _3: T; let mut _4: impl std::future::Future; @@ -21,12 +21,14 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) let mut _17: isize; let mut _18: (); let mut _19: u32; + let mut _20: &mut {async fn body of a()}; scope 1 { - debug x => (((*(_1.0: &mut {async fn body of a()})) as variant#4).0: T); + debug x => (((*_20) as variant#4).0: T); } bb0: { - _19 = discriminant((*(_1.0: &mut {async fn body of a()}))); + _20 = copy (_1.0: &mut {async fn body of a()}); + _19 = discriminant((*_20)); switchInt(move _19) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19]; } @@ -57,13 +59,13 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) bb6: { _0 = Poll::<()>::Pending; - discriminant((*(_1.0: &mut {async fn body of a()}))) = 4; + discriminant((*_20)) = 4; return; } bb7: { StorageLive(_16); - _15 = &mut (((*(_1.0: &mut {async fn body of a()})) as variant#4).1: impl std::future::Future); + _15 = &mut (((*_20) as variant#4).1: impl std::future::Future); _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb10, unwind: bb15]; } @@ -95,11 +97,11 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb14: { - drop(((*(_1.0: &mut {async fn body of a()})).0: T)) -> [return: bb13, unwind: bb4]; + drop(((*_20).0: T)) -> [return: bb13, unwind: bb4]; } bb15 (cleanup): { - discriminant((*(_1.0: &mut {async fn body of a()}))) = 2; + discriminant((*_20)) = 2; resume; } diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir index 2e2876cb3fcf2..6cad5b105d3e3 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -14,9 +14,11 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> let mut _0: std::task::Poll<()>; let mut _3: (); let mut _4: u32; + let mut _5: &mut {async fn body of a()}; bb0: { - _4 = discriminant((*(_1.0: &mut {async fn body of a()}))); + _5 = copy (_1.0: &mut {async fn body of a()}); + _4 = discriminant((*_5)); switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5]; } @@ -27,7 +29,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> bb2: { _0 = Poll::<()>::Ready(move _3); - discriminant((*(_1.0: &mut {async fn body of a()}))) = 1; + discriminant((*_5)) = 1; return; } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 20fc4112ef288..96ee37185db16 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -86,15 +86,16 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> let mut _36: (); let mut _37: (); let mut _38: u32; + let mut _39: &mut {async fn body of b()}; scope 1 { - debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}); + debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()}); let _17: (); scope 2 { debug result => _17; } } scope 3 { - debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}); + debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()}); let _33: (); scope 4 { debug result => _33; @@ -102,7 +103,8 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> } bb0: { - _38 = discriminant((*(_1.0: &mut {async fn body of b()}))); + _39 = copy (_1.0: &mut {async fn body of b()}); + _38 = discriminant((*_39)); switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8]; } @@ -121,7 +123,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_5); PlaceMention(_4); nop; - (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _4; + (((*_39) as variant#3).0: {async fn body of a()}) = move _4; goto -> bb4; } @@ -131,7 +133,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}); + _12 = &mut (((*_39) as variant#3).0: {async fn body of a()}); _11 = &mut (*_12); _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; } @@ -178,7 +180,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_4); StorageDead(_19); StorageDead(_20); - discriminant((*(_1.0: &mut {async fn body of b()}))) = 3; + discriminant((*_39)) = 3; return; } @@ -191,7 +193,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_12); StorageDead(_9); StorageDead(_8); - drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable]; + drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable]; } bb11: { @@ -223,7 +225,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_22); PlaceMention(_21); nop; - (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _21; + (((*_39) as variant#4).0: {async fn body of a()}) = move _21; goto -> bb16; } @@ -233,7 +235,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_26); StorageLive(_27); StorageLive(_28); - _28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}); + _28 = &mut (((*_39) as variant#4).0: {async fn body of a()}); _27 = &mut (*_28); _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; } @@ -275,7 +277,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_21); StorageDead(_35); StorageDead(_36); - discriminant((*(_1.0: &mut {async fn body of b()}))) = 4; + discriminant((*_39)) = 4; return; } @@ -288,7 +290,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_28); StorageDead(_25); StorageDead(_24); - drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable]; + drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable]; } bb22: { @@ -311,7 +313,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb25: { _0 = Poll::<()>::Ready(move _37); - discriminant((*(_1.0: &mut {async fn body of b()}))) = 1; + discriminant((*_39)) = 1; return; } diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir index cd776ad7170a3..b61215dc28cb4 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir @@ -23,7 +23,7 @@ } */ 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); + debug arg => (((*_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<'_>); @@ -41,13 +41,6 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 let mut _16: (); 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: { _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); @@ -56,14 +49,12 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 } bb1: { - _19 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - (((*_19) as variant#4).0: std::string::String) = move _2; + (((*_18) as variant#4).0: std::string::String) = move _2; StorageLive(_3); StorageLive(_4); StorageLive(_5); StorageLive(_6); - _20 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - _6 = &(((*_20) as variant#4).0: std::string::String); + _6 = &(((*_18) as variant#4).0: std::string::String); _5 = ::clone(move _6) -> [return: bb2, unwind unreachable]; } @@ -84,8 +75,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); StorageDead(_3); StorageDead(_4); - _21 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - discriminant((*_21)) = 3; + discriminant((*_18)) = 3; return; } @@ -108,8 +98,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 _10 = &(*_11); StorageLive(_12); StorageLive(_13); - _22 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - _13 = &(((*_22) as variant#4).0: std::string::String); + _13 = &(((*_18) as variant#4).0: std::string::String); _12 = ::clone(move _13) -> [return: bb8, unwind unreachable]; } @@ -135,8 +124,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageDead(_9); StorageDead(_11); StorageDead(_15); - _23 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - discriminant((*_23)) = 4; + discriminant((*_18)) = 4; return; } @@ -154,8 +142,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageDead(_11); StorageDead(_8); _16 = const (); - _24 = 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]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable]; } bb14: { @@ -164,8 +151,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb15: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); - _25 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); - discriminant((*_25)) = 1; + discriminant((*_18)) = 1; return; } diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir index 981bc21dc878a..aac028a9e6c0e 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir @@ -23,7 +23,7 @@ } */ 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); + debug arg => (((*_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<'_>); @@ -41,13 +41,6 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 let mut _16: (); 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: { _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); @@ -56,14 +49,12 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 } bb1: { - _19 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - (((*_19) as variant#4).0: std::string::String) = move _2; + (((*_18) as variant#4).0: std::string::String) = move _2; StorageLive(_3); StorageLive(_4); StorageLive(_5); StorageLive(_6); - _20 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - _6 = &(((*_20) as variant#4).0: std::string::String); + _6 = &(((*_18) as variant#4).0: std::string::String); _5 = ::clone(move _6) -> [return: bb2, unwind unreachable]; } @@ -84,8 +75,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); StorageDead(_3); StorageDead(_4); - _21 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - discriminant((*_21)) = 3; + discriminant((*_18)) = 3; return; } @@ -108,8 +98,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 _10 = &(*_11); StorageLive(_12); StorageLive(_13); - _22 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - _13 = &(((*_22) as variant#4).0: std::string::String); + _13 = &(((*_18) as variant#4).0: std::string::String); _12 = ::clone(move _13) -> [return: bb8, unwind unreachable]; } @@ -135,8 +124,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageDead(_9); StorageDead(_11); StorageDead(_15); - _23 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - discriminant((*_23)) = 4; + discriminant((*_18)) = 4; return; } @@ -154,8 +142,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageDead(_11); StorageDead(_8); _16 = const (); - _24 = 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]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable]; } bb14: { @@ -164,8 +151,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb15: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); - _25 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); - discriminant((*_25)) = 1; + discriminant((*_18)) = 1; return; } diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 9905cc3e00f99..222c7144ef07d 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -32,18 +32,20 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} let _8: (); let mut _9: (); let mut _10: u32; + let mut _11: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}; scope 1 { - debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop); + debug _d => (((*_11) as variant#3).0: HasDrop); } bb0: { - _10 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))); + _11 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}); + _10 = discriminant((*_11)); switchInt(move _10) -> [0: bb1, 3: bb5, otherwise: bb6]; } bb1: { nop; - (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop; + (((*_11) as variant#3).0: HasDrop) = HasDrop; StorageLive(_4); goto -> bb2; } @@ -56,7 +58,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} StorageDead(_4); StorageDead(_6); StorageDead(_7); - discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))) = 3; + discriminant((*_11)) = 3; return; } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 4ca8dbbc76f07..4c1b25c786efc 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -41,13 +41,6 @@ + let mut _30: (); + 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()}; -+ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()}; -+ 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()}; + scope 7 { + let mut _15: std::future::Ready<()>; + scope 8 { @@ -57,37 +50,37 @@ + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 13 (inlined as Future>::poll) { -+ 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<()>>; ++ let mut _34: (); ++ let mut _35: std::option::Option<()>; ++ let mut _36: &mut std::option::Option<()>; ++ let mut _37: &mut std::future::Ready<()>; ++ let mut _38: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ let mut _46: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; -+ let mut _47: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _39: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; ++ let mut _40: *mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 15 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { -+ let mut _48: &mut &mut std::future::Ready<()>; ++ let mut _41: &mut &mut std::future::Ready<()>; + scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } + } + scope 17 (inlined Option::<()>::take) { -+ let mut _49: std::option::Option<()>; ++ let mut _42: std::option::Option<()>; + scope 18 (inlined std::mem::replace::>) { + scope 19 { + } + } + } + scope 20 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _50: isize; -+ let mut _51: !; ++ let mut _43: isize; ++ let mut _44: !; + scope 21 { + } + } + } + } + scope 10 (inlined ready::<()>) { -+ let mut _40: std::option::Option<()>; ++ let mut _33: std::option::Option<()>; + } + scope 11 (inlined as IntoFuture>::into_future) { + } @@ -132,13 +125,6 @@ + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); -+ StorageLive(_33); -+ StorageLive(_34); -+ StorageLive(_35); -+ StorageLive(_36); -+ StorageLive(_37); -+ StorageLive(_38); -+ StorageLive(_39); + _32 = 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]; @@ -151,13 +137,6 @@ + } + + bb2: { -+ StorageDead(_39); -+ StorageDead(_38); -+ StorageDead(_37); -+ StorageDead(_36); -+ StorageDead(_35); -+ StorageDead(_34); -+ StorageDead(_33); + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); @@ -175,22 +154,19 @@ } + bb3: { -+ _33 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _34 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>); ++ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = (); -+ StorageLive(_40); -+ _40 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _40); -+ StorageDead(_40); ++ StorageLive(_33); ++ _33 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _33); ++ StorageDead(_33); + StorageDead(_14); + _12 = move _13; + StorageDead(_13); -+ _35 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12; ++ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb4; + } + @@ -202,8 +178,7 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _36 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>); ++ _21 = &mut (((*_32) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); @@ -214,24 +189,24 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); ++ StorageLive(_37); ++ StorageLive(_39); + StorageLive(_44); -+ StorageLive(_46); -+ StorageLive(_51); -+ StorageLive(_41); ++ StorageLive(_34); ++ StorageLive(_35); ++ StorageLive(_40); ++ _40 = &raw mut _19; ++ _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); ++ StorageDead(_40); ++ _37 = copy ((*_39).0: &mut std::future::Ready<()>); + StorageLive(_42); -+ StorageLive(_47); -+ _47 = &raw mut _19; -+ _46 = copy _47 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_47); -+ _44 = copy ((*_46).0: &mut std::future::Ready<()>); -+ StorageLive(_49); -+ _49 = Option::<()>::None; -+ _42 = copy ((*_44).0: std::option::Option<()>); -+ ((*_44).0: std::option::Option<()>) = copy _49; -+ StorageDead(_49); -+ StorageLive(_50); -+ _50 = discriminant(_42); -+ switchInt(move _50) -> [0: bb11, 1: bb12, otherwise: bb5]; ++ _42 = Option::<()>::None; ++ _35 = copy ((*_37).0: std::option::Option<()>); ++ ((*_37).0: std::option::Option<()>) = copy _42; ++ StorageDead(_42); ++ StorageLive(_43); ++ _43 = discriminant(_35); ++ switchInt(move _43) -> [0: bb11, 1: bb12, otherwise: bb5]; } + + bb5: { @@ -251,8 +226,7 @@ + StorageDead(_12); + StorageDead(_28); + StorageDead(_29); -+ _37 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_37)) = 3; ++ discriminant((*_32)) = 3; + goto -> bb2; + } + @@ -266,14 +240,12 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ _38 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; + } + + bb8: { + _7 = Poll::<()>::Ready(move _30); -+ _39 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_39)) = 1; ++ discriminant((*_32)) = 1; + goto -> bb2; + } + @@ -294,18 +266,18 @@ + } + + bb11: { -+ _51 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ _44 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; + } + + bb12: { -+ _41 = move ((_42 as Some).0: ()); -+ StorageDead(_50); -+ StorageDead(_42); -+ _18 = Poll::<()>::Ready(move _41); -+ StorageDead(_41); -+ StorageDead(_51); -+ StorageDead(_46); ++ _34 = move ((_35 as Some).0: ()); ++ StorageDead(_43); ++ StorageDead(_35); ++ _18 = Poll::<()>::Ready(move _34); ++ StorageDead(_34); + StorageDead(_44); ++ StorageDead(_39); ++ StorageDead(_37); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 6ce8693007b92..59417ce646513 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -41,15 +41,6 @@ + let mut _30: (); + 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()}; -+ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()}; -+ 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()}; -+ let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()}; + scope 7 { + let mut _15: std::future::Ready<()>; + scope 8 { @@ -59,37 +50,37 @@ + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 13 (inlined as Future>::poll) { -+ 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<()>>; ++ let mut _34: (); ++ let mut _35: std::option::Option<()>; ++ let mut _36: &mut std::option::Option<()>; ++ let mut _37: &mut std::future::Ready<()>; ++ let mut _38: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ let mut _48: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; -+ let mut _49: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _39: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; ++ let mut _40: *mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 15 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { -+ let mut _50: &mut &mut std::future::Ready<()>; ++ let mut _41: &mut &mut std::future::Ready<()>; + scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } + } + scope 17 (inlined Option::<()>::take) { -+ let mut _51: std::option::Option<()>; ++ let mut _42: std::option::Option<()>; + scope 18 (inlined std::mem::replace::>) { + scope 19 { + } + } + } + scope 20 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _52: isize; -+ let mut _53: !; ++ let mut _43: isize; ++ let mut _44: !; + scope 21 { + } + } + } + } + scope 10 (inlined ready::<()>) { -+ let mut _42: std::option::Option<()>; ++ let mut _33: std::option::Option<()>; + } + scope 11 (inlined as IntoFuture>::into_future) { + } @@ -134,15 +125,6 @@ + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); -+ StorageLive(_33); -+ StorageLive(_34); -+ StorageLive(_35); -+ StorageLive(_36); -+ StorageLive(_37); -+ StorageLive(_38); -+ StorageLive(_39); -+ StorageLive(_40); -+ StorageLive(_41); + _32 = 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]; @@ -163,15 +145,6 @@ + } + + bb4: { -+ StorageDead(_41); -+ StorageDead(_40); -+ StorageDead(_39); -+ StorageDead(_38); -+ StorageDead(_37); -+ StorageDead(_36); -+ StorageDead(_35); -+ StorageDead(_34); -+ StorageDead(_33); + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); @@ -192,22 +165,19 @@ - StorageDead(_2); - return; + bb5: { -+ _33 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _34 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>); ++ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = (); -+ StorageLive(_42); -+ _42 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _42); -+ StorageDead(_42); ++ StorageLive(_33); ++ _33 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _33); ++ StorageDead(_33); + StorageDead(_14); + _12 = move _13; + StorageDead(_13); -+ _35 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12; ++ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb6; } @@ -219,8 +189,7 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _36 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>); ++ _21 = &mut (((*_32) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); @@ -231,24 +200,24 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); -+ StorageLive(_46); -+ StorageLive(_48); -+ StorageLive(_53); -+ StorageLive(_43); ++ StorageLive(_37); ++ StorageLive(_39); + StorageLive(_44); -+ StorageLive(_49); -+ _49 = &raw mut _19; -+ _48 = copy _49 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ StorageDead(_49); -+ _46 = copy ((*_48).0: &mut std::future::Ready<()>); -+ StorageLive(_51); -+ _51 = Option::<()>::None; -+ _44 = copy ((*_46).0: std::option::Option<()>); -+ ((*_46).0: std::option::Option<()>) = copy _51; -+ StorageDead(_51); -+ StorageLive(_52); -+ _52 = discriminant(_44); -+ switchInt(move _52) -> [0: bb16, 1: bb17, otherwise: bb7]; ++ StorageLive(_34); ++ StorageLive(_35); ++ StorageLive(_40); ++ _40 = &raw mut _19; ++ _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); ++ StorageDead(_40); ++ _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageLive(_42); ++ _42 = Option::<()>::None; ++ _35 = copy ((*_37).0: std::option::Option<()>); ++ ((*_37).0: std::option::Option<()>) = copy _42; ++ StorageDead(_42); ++ StorageLive(_43); ++ _43 = discriminant(_35); ++ switchInt(move _43) -> [0: bb16, 1: bb17, otherwise: bb7]; } - bb6 (cleanup): { @@ -270,8 +239,7 @@ + StorageDead(_12); + StorageDead(_28); + StorageDead(_29); -+ _37 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_37)) = 3; ++ discriminant((*_32)) = 3; + goto -> bb4; + } + @@ -285,14 +253,12 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ _38 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; + } + + bb10: { + _7 = Poll::<()>::Ready(move _30); -+ _39 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_39)) = 1; ++ discriminant((*_32)) = 1; + goto -> bb4; + } + @@ -304,13 +270,11 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ _40 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { -+ _41 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_41)) = 2; ++ discriminant((*_32)) = 2; + goto -> bb2; + } + @@ -335,18 +299,18 @@ + } + + bb16: { -+ _53 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ _44 = option::expect_failed(const "`Ready` polled after completion") -> bb11; + } + + bb17: { -+ _43 = move ((_44 as Some).0: ()); -+ StorageDead(_52); -+ StorageDead(_44); -+ _18 = Poll::<()>::Ready(move _43); ++ _34 = move ((_35 as Some).0: ()); + StorageDead(_43); -+ StorageDead(_53); -+ StorageDead(_48); -+ StorageDead(_46); ++ StorageDead(_35); ++ _18 = Poll::<()>::Ready(move _34); ++ StorageDead(_34); ++ StorageDead(_44); ++ StorageDead(_39); ++ StorageDead(_37); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index 550f0512569d7..3ec816b657f45 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -42,10 +42,8 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo let mut _5: (); let mut _6: u32; let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; debug _task_context => _2; - debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); + debug y => (*((*_7).0: &i32)); debug y => _3; bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); @@ -54,14 +52,12 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo } bb1: { StorageLive(_3); - _8 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); - _4 = ((*_8).0: &i32); + _4 = ((*_7).0: &i32); _3 = (*_4); _5 = (); StorageDead(_3); _0 = std::task::Poll::Ready(move _5); - _9 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); - discriminant((*_9)) = 1; + discriminant((*_7)) = 1; return; } bb2: { @@ -78,10 +74,8 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c let mut _5: (); let mut _6: u32; let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _8: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - let mut _9: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; debug _task_context => _2; - debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32)); + debug y => (*((*_7).0: &i32)); debug y => _3; bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); @@ -90,14 +84,12 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c } bb1: { StorageLive(_3); - _8 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); - _4 = ((*_8).0: &i32); + _4 = ((*_7).0: &i32); _3 = (*_4); _5 = (); StorageDead(_3); _0 = std::task::Poll::Ready(move _5); - _9 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); - discriminant((*_9)) = 1; + discriminant((*_7)) = 1; return; } bb2: { From 536f126aca6597c42ed2f97e1ae1ae4bb34ca34c Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Wed, 8 Oct 2025 22:45:09 +0000 Subject: [PATCH 2/7] Insert assignment after Retag. --- compiler/rustc_mir_transform/src/coroutine.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4094ad470770a..94ddc76be0874 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -551,8 +551,15 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let source_info = SourceInfo::outermost(body.span); let pin_field = tcx.mk_place_field(SELF_ARG.into(), FieldIdx::ZERO, ref_coroutine_ty); - body.basic_blocks_mut()[START_BLOCK].statements.insert( - 0, + let statements = &mut body.basic_blocks.as_mut_preserves_cfg()[START_BLOCK].statements; + // Miri requires retags to be the very first thing in the body. + // We insert this assignment just after. + let insert_point = statements + .iter() + .position(|stmt| !matches!(stmt.kind, StatementKind::Retag(..))) + .unwrap_or(statements.len()); + statements.insert( + insert_point, Statement::new( source_info, StatementKind::Assign(Box::new(( From ae978c163ebf8fa44eb906753a9813dcb0fb6d71 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 9 Aug 2023 21:11:35 +0000 Subject: [PATCH 3/7] Support Yield in ops. --- .../src/dataflow_const_prop.rs | 11 +++++++--- compiler/rustc_mir_transform/src/gvn.rs | 20 +++++++++++-------- .../rustc_mir_transform/src/jump_threading.rs | 7 ++++--- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index aae86a43127d9..8b9ee1833f7dc 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -46,6 +46,12 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { return; } + // Avoid computing layout inside coroutines, since their `optimized_mir` is used for layout + // computation, which can create a cycle. + if body.coroutine.is_some() { + return; + } + // We want to have a somewhat linear runtime w.r.t. the number of statements/terminators. // Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function // applications, where `h` is the height of the lattice. Because the height of our lattice @@ -237,9 +243,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { TerminatorKind::Drop { place, .. } => { state.flood_with(place.as_ref(), &self.map, FlatSet::::BOTTOM); } - TerminatorKind::Yield { .. } => { - // They would have an effect, but are not allowed in this phase. - bug!("encountered disallowed terminator"); + TerminatorKind::Yield { resume_arg, .. } => { + state.flood_with(resume_arg.as_ref(), &self.map, FlatSet::::BOTTOM); } TerminatorKind::SwitchInt { discr, targets } => { return self.handle_switch_int(discr, targets, state); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 2f857ea45ac72..6b15b1022aa7e 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1911,14 +1911,18 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { } fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { - if let Terminator { kind: TerminatorKind::Call { destination, .. }, .. } = terminator { - if let Some(local) = destination.as_local() - && self.ssa.is_ssa(local) - { - let ty = self.local_decls[local].ty; - let opaque = self.new_opaque(ty); - self.assign(local, opaque); - } + let destination = match terminator.kind { + TerminatorKind::Call { destination, .. } => Some(destination), + TerminatorKind::Yield { resume_arg, .. } => Some(resume_arg), + _ => None, + }; + if let Some(destination) = destination + && let Some(local) = destination.as_local() + && self.ssa.is_ssa(local) + { + let ty = self.local_decls[local].ty; + let opaque = self.new_opaque(ty); + self.assign(local, opaque); } // Function calls and ASM may invalidate (nested) derefs. We must handle them carefully. // Currently, only preserving derefs for trivial terminators like SwitchInt and Goto. diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 59aa811aa73e8..be809f71da2bc 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -610,9 +610,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { | TerminatorKind::Unreachable | TerminatorKind::CoroutineDrop => bug!("{term:?} has no terminators"), // Disallowed during optimizations. - TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Yield { .. } => bug!("{term:?} invalid"), + TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { + bug!("{term:?} invalid") + } // Cannot reason about inline asm. TerminatorKind::InlineAsm { .. } => return, // `SwitchInt` is handled specially. @@ -621,6 +621,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { TerminatorKind::Goto { .. } => None, // Flood the overwritten place, and progress through. TerminatorKind::Drop { place: destination, .. } + | TerminatorKind::Yield { resume_arg: destination, .. } | TerminatorKind::Call { destination, .. } => Some(destination), // Ignore, as this can be a no-op at codegen time. TerminatorKind::Assert { .. } => None, From b1e9bbf382e944a84e2eb55d4615482fbef93ca3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 25 Sep 2023 18:49:14 +0000 Subject: [PATCH 4/7] Remove validation. --- compiler/rustc_mir_transform/src/validate.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 2945298c3fdda..3e02d04ee2c86 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -451,7 +451,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`Yield` cannot appear outside coroutine bodies"); } - if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) { self.fail(location, "`Yield` should have been replaced by coroutine lowering"); } self.check_edge(location, *resume, EdgeKind::Normal); @@ -489,7 +489,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { if self.body.coroutine.is_none() { self.fail(location, "`CoroutineDrop` cannot appear outside coroutine bodies"); } - if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Optimized) { self.fail( location, "`CoroutineDrop` should have been replaced by coroutine lowering", From e90ccd9fc8185d5e413419fda0615810e56b9ced Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Tue, 12 Aug 2025 22:47:28 +0000 Subject: [PATCH 5/7] Move state transform after optimizations. --- compiler/rustc_mir_transform/src/coroutine.rs | 3 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 1 - .../src/shim/async_destructor_ctor.rs | 1 + ...#0}.coroutine_drop_async.0.panic-abort.mir | 40 ++++----- ...0}.coroutine_drop_async.0.panic-unwind.mir | 70 +++++++--------- ...await.b-{closure#0}.coroutine_resume.0.mir | 70 +++++++--------- ....main-{closure#0}.StateTransform.after.mir | 64 ++++++-------- ....main-{closure#1}.StateTransform.after.mir | 64 ++++++-------- ...losure#0}.coroutine_drop.0.panic-abort.mir | 9 +- ...osure#0}.coroutine_drop.0.panic-unwind.mir | 9 +- ...e#0}.StateTransform.before.panic-abort.mir | 52 ++++-------- ...#0}.StateTransform.before.panic-unwind.mir | 84 +++++++------------ ...ny.main-{closure#0}.coroutine_resume.0.mir | 48 ++++------- ...ine_coroutine.main.Inline.panic-abort.diff | 6 +- ...ne_coroutine.main.Inline.panic-unwind.diff | 6 +- .../future-sizes/async-awaiting-fut.rs | 2 +- .../future-sizes/async-awaiting-fut.stdout | 37 ++++---- tests/ui/coroutine/size-moved-locals.rs | 2 +- .../coroutine_discr_placement.stdout | 16 +--- .../async-closure.stdout | 28 +++++-- 21 files changed, 252 insertions(+), 362 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 94ddc76be0874..b9fd1cabdea15 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -174,6 +174,7 @@ const SELF_ARG: Local = Local::from_u32(1); const CTX_ARG: Local = Local::from_u32(2); /// A `yield` point in the coroutine. +#[derive(Debug)] struct SuspensionPoint<'tcx> { /// State discriminant used when suspending or resuming at this point. state: usize, @@ -656,7 +657,7 @@ fn replace_resume_ty_local<'tcx>( // We have to replace the `ResumeTy` that is used for type and borrow checking // with `&mut Context<'_>` in MIR. #[cfg(debug_assertions)] - { + if local_ty != context_mut_ref { if let ty::Adt(resume_ty_adt, _) = local_ty.kind() { let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, body.span)); assert_eq!(*resume_ty_adt, expected_adt); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 3ffd263fab027..ae0b90e928e79 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -626,7 +626,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &add_retag::AddRetag, &erase_deref_temps::EraseDerefTemps, &elaborate_box_derefs::ElaborateBoxDerefs, - &coroutine::StateTransform, &Lint(known_panics_lint::KnownPanicsLint), ]; pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial))); @@ -732,6 +731,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, &large_enums::EnumSizeOpt { discrepancy: 128 }, + &coroutine::StateTransform, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, // Cleanup for human readability, off by default. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 85e340c0a02ab..37ac90f088132 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -150,7 +150,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< tcx, &mut body, &[ - &mentioned_items::MentionedItems, &abort_unwinding_calls::AbortUnwindingCalls, &add_call_guards::CriticalCallEdges, ], diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index a0f1260cd986d..f4bcb4d3bcd06 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -216,6 +216,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( body.source.instance = instance; body.phase = MirPhase::Runtime(RuntimePhase::Initial); body.var_debug_info.clear(); + body.mentioned_items = None; let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span)); let args = tcx.mk_args(&[proxy_ref.into()]); let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args); diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir index 435c1532895ca..0e7aa6167f462 100644 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -29,72 +29,68 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) bb0: { _20 = copy (_1.0: &mut {async fn body of a()}); _19 = discriminant((*_20)); - switchInt(move _19) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14]; + switchInt(move _19) -> [0: bb8, 3: bb11, 4: bb12, otherwise: bb13]; } bb1: { nop; nop; - goto -> bb2; - } - - bb2: { _0 = Poll::<()>::Ready(const ()); return; } - bb3: { + bb2: { _0 = Poll::<()>::Pending; discriminant((*_20)) = 4; return; } - bb4: { + bb3: { StorageLive(_16); _15 = &mut (((*_20) as variant#4).1: impl std::future::Future); - _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb7, unwind unreachable]; + _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb6, unwind unreachable]; } - bb5: { + bb4: { unreachable; } - bb6: { + bb5: { StorageDead(_16); _17 = discriminant(_9); - switchInt(move _17) -> [0: bb1, 1: bb3, otherwise: bb5]; + switchInt(move _17) -> [0: bb1, 1: bb2, otherwise: bb4]; } - bb7: { - _9 = as Future>::poll(move _16, move _14) -> [return: bb6, unwind unreachable]; + bb6: { + _9 = as Future>::poll(move _16, move _14) -> [return: bb5, unwind unreachable]; } - bb8: { + bb7: { _0 = Poll::<()>::Ready(const ()); return; } + bb8: { + goto -> bb10; + } + bb9: { - goto -> bb11; + goto -> bb7; } bb10: { - goto -> bb8; + drop(((*_20).0: T)) -> [return: bb9, unwind unreachable]; } bb11: { - drop(((*_20).0: T)) -> [return: bb10, unwind unreachable]; + goto -> bb3; } bb12: { - goto -> bb4; + goto -> bb3; } bb13: { - goto -> bb4; - } - - bb14: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir index 1dc1d08136290..82f2091d4a1a8 100644 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -29,95 +29,81 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) bb0: { _20 = copy (_1.0: &mut {async fn body of a()}); _19 = discriminant((*_20)); - switchInt(move _19) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19]; + switchInt(move _19) -> [0: bb8, 2: bb15, 3: bb13, 4: bb14, otherwise: bb16]; } bb1: { nop; nop; - goto -> bb2; - } - - bb2: { _0 = Poll::<()>::Ready(const ()); return; } - bb3 (cleanup): { - nop; - nop; - goto -> bb5; - } - - bb4 (cleanup): { - goto -> bb15; - } - - bb5 (cleanup): { - goto -> bb4; - } - - bb6: { + bb2: { _0 = Poll::<()>::Pending; discriminant((*_20)) = 4; return; } - bb7: { + bb3: { StorageLive(_16); _15 = &mut (((*_20) as variant#4).1: impl std::future::Future); - _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb10, unwind: bb15]; + _16 = Pin::<&mut impl Future>::new_unchecked(move _15) -> [return: bb6, unwind: bb12]; } - bb8: { + bb4: { unreachable; } - bb9: { + bb5: { StorageDead(_16); _17 = discriminant(_9); - switchInt(move _17) -> [0: bb1, 1: bb6, otherwise: bb8]; + switchInt(move _17) -> [0: bb1, 1: bb2, otherwise: bb4]; } - bb10: { - _9 = as Future>::poll(move _16, move _14) -> [return: bb9, unwind: bb3]; + bb6: { + _9 = as Future>::poll(move _16, move _14) -> [return: bb5, unwind: bb12]; } - bb11: { + bb7: { _0 = Poll::<()>::Ready(const ()); return; } - bb12: { - goto -> bb14; + bb8: { + goto -> bb11; } - bb13: { - goto -> bb11; + bb9 (cleanup): { + goto -> bb12; } - bb14: { - drop(((*_20).0: T)) -> [return: bb13, unwind: bb4]; + bb10: { + goto -> bb7; } - bb15 (cleanup): { + bb11: { + drop(((*_20).0: T)) -> [return: bb10, unwind: bb9]; + } + + bb12 (cleanup): { discriminant((*_20)) = 2; resume; } - bb16: { - goto -> bb7; + bb13: { + goto -> bb3; } - bb17: { - goto -> bb7; + bb14: { + goto -> bb3; } - bb18: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue]; + bb15: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb15, unwind continue]; } - bb19: { + bb16: { _0 = Poll::<()>::Ready(const ()); return; } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 96ee37185db16..7cf9c28664c23 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -105,7 +105,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb0: { _39 = copy (_1.0: &mut {async fn body of b()}); _38 = discriminant((*_39)); - switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8]; + switchInt(move _38) -> [0: bb1, 1: bb27, 3: bb25, 4: bb26, otherwise: bb8]; } bb1: { @@ -121,7 +121,6 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb3: { StorageDead(_5); - PlaceMention(_4); nop; (((*_39) as variant#3).0: {async fn body of a()}) = move _4; goto -> bb4; @@ -157,7 +156,6 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb7: { StorageDead(_13); StorageDead(_10); - PlaceMention(_9); _16 = discriminant(_9); switchInt(move _16) -> [0: bb10, 1: bb9, otherwise: bb8]; } @@ -206,30 +204,25 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb12: { nop; - goto -> bb13; - } - - bb13: { StorageDead(_4); StorageDead(_3); StorageLive(_21); StorageLive(_22); - _22 = a() -> [return: bb14, unwind unreachable]; + _22 = a() -> [return: bb13, unwind unreachable]; } - bb14: { - _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + bb13: { + _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb14, unwind unreachable]; } - bb15: { + bb14: { StorageDead(_22); - PlaceMention(_21); nop; (((*_39) as variant#4).0: {async fn body of a()}) = move _21; - goto -> bb16; + goto -> bb15; } - bb16: { + bb15: { StorageLive(_24); StorageLive(_25); StorageLive(_26); @@ -237,34 +230,33 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_28); _28 = &mut (((*_39) as variant#4).0: {async fn body of a()}); _27 = &mut (*_28); - _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; + _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb16, unwind unreachable]; } - bb17: { + bb16: { StorageDead(_27); StorageLive(_29); StorageLive(_30); StorageLive(_31); _31 = copy _2; _30 = move _31; - goto -> bb18; + goto -> bb17; } - bb18: { + bb17: { _29 = &mut (*_30); StorageDead(_31); - _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; + _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb18, unwind unreachable]; } - bb19: { + bb18: { StorageDead(_29); StorageDead(_26); - PlaceMention(_25); _32 = discriminant(_25); - switchInt(move _32) -> [0: bb21, 1: bb20, otherwise: bb8]; + switchInt(move _32) -> [0: bb20, 1: bb19, otherwise: bb8]; } - bb20: { + bb19: { _24 = const (); StorageDead(_30); StorageDead(_28); @@ -281,7 +273,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> return; } - bb21: { + bb20: { StorageLive(_33); _33 = copy ((_25 as Ready).0: ()); _37 = copy _33; @@ -290,38 +282,34 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_28); StorageDead(_25); StorageDead(_24); - drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable]; + drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb22, unwind unreachable]; } - bb22: { + bb21: { StorageDead(_36); _2 = move _35; StorageDead(_35); _7 = const (); - goto -> bb16; + goto -> bb15; } - bb23: { + bb22: { nop; - goto -> bb24; - } - - bb24: { StorageDead(_21); - goto -> bb26; + goto -> bb24; } - bb25: { + bb23: { _0 = Poll::<()>::Ready(move _37); discriminant((*_39)) = 1; return; } - bb26: { - goto -> bb25; + bb24: { + goto -> bb23; } - bb27: { + bb25: { StorageLive(_3); StorageLive(_4); StorageLive(_19); @@ -330,15 +318,15 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> goto -> bb11; } - bb28: { + bb26: { StorageLive(_21); StorageLive(_35); StorageLive(_36); _35 = move _2; - goto -> bb22; + goto -> bb21; } - bb29: { - assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; + bb27: { + assert(const false, "`async fn` resumed after completion") -> [success: bb27, unwind unreachable]; } } diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir index b61215dc28cb4..428d29fc518ad 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir @@ -45,7 +45,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb0: { _18 = 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]; + switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16]; } bb1: { @@ -67,10 +67,6 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb3: { _4 = (const "first", move _5, move _7); StorageDead(_7); - goto -> bb4; - } - - bb4: { StorageDead(_5); _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); StorageDead(_3); @@ -79,16 +75,12 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 return; } - bb5: { - goto -> bb6; - } - - bb6: { + bb4: { StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; + drop(_3) -> [return: bb5, unwind unreachable]; } - bb7: { + bb5: { StorageDead(_3); StorageLive(_8); StorageLive(_9); @@ -99,24 +91,20 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageLive(_12); StorageLive(_13); _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb8, unwind unreachable]; + _12 = ::clone(move _13) -> [return: bb6, unwind unreachable]; } - bb8: { + bb6: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable]; } - bb9: { + bb7: { _14 = &(*_15); _9 = (move _10, move _12, move _14); StorageDead(_14); - goto -> bb10; - } - - bb10: { StorageDead(_12); StorageDead(_10); _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9); @@ -128,58 +116,54 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 return; } - bb11: { - goto -> bb12; - } - - bb12: { + bb8: { StorageDead(_9); - drop(_8) -> [return: bb13, unwind unreachable]; + drop(_8) -> [return: bb9, unwind unreachable]; } - bb13: { + bb9: { StorageDead(_15); StorageDead(_11); StorageDead(_8); _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable]; } - bb14: { - goto -> bb16; + bb10: { + goto -> bb12; } - bb15: { + bb11: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); discriminant((*_18)) = 1; return; } - bb16: { - goto -> bb15; + bb12: { + goto -> bb11; } - bb17: { + bb13: { StorageLive(_3); StorageLive(_4); _3 = move _2; - goto -> bb5; + goto -> bb4; } - bb18: { + bb14: { StorageLive(_8); StorageLive(_9); StorageLive(_11); StorageLive(_15); _8 = move _2; - goto -> bb11; + goto -> bb8; } - bb19: { - assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable]; + bb15: { + assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable]; } - bb20: { + bb16: { unreachable; } } diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir index aac028a9e6c0e..23d0afa337deb 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir @@ -45,7 +45,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb0: { _18 = 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]; + switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16]; } bb1: { @@ -67,10 +67,6 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb3: { _4 = (const "first", move _5, move _7); StorageDead(_7); - goto -> bb4; - } - - bb4: { StorageDead(_5); _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); StorageDead(_3); @@ -79,16 +75,12 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 return; } - bb5: { - goto -> bb6; - } - - bb6: { + bb4: { StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; + drop(_3) -> [return: bb5, unwind unreachable]; } - bb7: { + bb5: { StorageDead(_3); StorageLive(_8); StorageLive(_9); @@ -99,24 +91,20 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageLive(_12); StorageLive(_13); _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb8, unwind unreachable]; + _12 = ::clone(move _13) -> [return: bb6, unwind unreachable]; } - bb8: { + bb6: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable]; } - bb9: { + bb7: { _14 = &(*_15); _9 = (move _10, move _12, move _14); StorageDead(_14); - goto -> bb10; - } - - bb10: { StorageDead(_12); StorageDead(_10); _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9); @@ -128,58 +116,54 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 return; } - bb11: { - goto -> bb12; - } - - bb12: { + bb8: { StorageDead(_9); - drop(_8) -> [return: bb13, unwind unreachable]; + drop(_8) -> [return: bb9, unwind unreachable]; } - bb13: { + bb9: { StorageDead(_15); StorageDead(_11); StorageDead(_8); _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable]; } - bb14: { - goto -> bb16; + bb10: { + goto -> bb12; } - bb15: { + bb11: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); discriminant((*_18)) = 1; return; } - bb16: { - goto -> bb15; + bb12: { + goto -> bb11; } - bb17: { + bb13: { StorageLive(_3); StorageLive(_4); _3 = move _2; - goto -> bb5; + goto -> bb4; } - bb18: { + bb14: { StorageLive(_8); StorageLive(_9); StorageLive(_11); StorageLive(_15); _8 = move _2; - goto -> bb11; + goto -> bb8; } - bb19: { - assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable]; + bb15: { + assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable]; } - bb20: { + bb16: { unreachable; } } diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir index 33fbca7f77ed1..8d947ab30abad 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir @@ -6,19 +6,17 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 let _3: std::string::String; let _4: (); let mut _5: (); - let mut _6: (); - let mut _7: u32; + let mut _6: u32; scope 1 { debug _s => (((*_1) as variant#3).0: std::string::String); } bb0: { - _7 = discriminant((*_1)); - switchInt(move _7) -> [0: bb5, 3: bb8, otherwise: bb9]; + _6 = discriminant((*_1)); + switchInt(move _6) -> [0: bb5, 3: bb8, otherwise: bb9]; } bb1: { - StorageDead(_5); StorageDead(_4); drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind unreachable]; } @@ -50,7 +48,6 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb8: { StorageLive(_4); - StorageLive(_5); goto -> bb1; } diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir index 69e7219af9ff8..52a8747e00ebf 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir @@ -6,19 +6,17 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 let _3: std::string::String; let _4: (); let mut _5: (); - let mut _6: (); - let mut _7: u32; + let mut _6: u32; scope 1 { debug _s => (((*_1) as variant#3).0: std::string::String); } bb0: { - _7 = discriminant((*_1)); - switchInt(move _7) -> [0: bb7, 3: bb10, otherwise: bb11]; + _6 = discriminant((*_1)); + switchInt(move _6) -> [0: bb7, 3: bb10, otherwise: bb11]; } bb1: { - StorageDead(_5); StorageDead(_4); drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; } @@ -59,7 +57,6 @@ fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12 bb10: { StorageLive(_4); - StorageLive(_5); goto -> bb1; } diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir index 4731aed335d9f..1f389761317f6 100644 --- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir +++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir @@ -6,11 +6,9 @@ yields () let mut _0: (); let _3: Foo; let _5: (); - let mut _6: (); - let _7: (); - let mut _8: Foo; - let _9: (); - let mut _10: Bar; + let _6: (); + let mut _7: Foo; + let _8: (); scope 1 { debug a => _3; let _4: Bar; @@ -22,62 +20,48 @@ yields () bb0: { StorageLive(_3); _3 = Foo(const 5_i32); - StorageLive(_4); _4 = Bar(const 6_i32); StorageLive(_5); - StorageLive(_6); - _6 = (); - _5 = yield(move _6) -> [resume: bb1, drop: bb6]; + _5 = yield(const ()) -> [resume: bb1, drop: bb5]; } bb1: { - StorageDead(_6); StorageDead(_5); + StorageLive(_6); StorageLive(_7); - StorageLive(_8); - _8 = move _3; - _7 = take::(move _8) -> [return: bb2, unwind unreachable]; + _7 = move _3; + _6 = take::(move _7) -> [return: bb2, unwind unreachable]; } bb2: { - StorageDead(_8); StorageDead(_7); - StorageLive(_9); - StorageLive(_10); - _10 = move _4; - _9 = take::(move _10) -> [return: bb3, unwind unreachable]; + StorageDead(_6); + StorageLive(_8); + _8 = take::(move _4) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_10); - StorageDead(_9); + StorageDead(_8); _0 = const (); - StorageDead(_4); - goto -> bb4; - } - - bb4: { StorageDead(_3); - drop(_1) -> [return: bb5, unwind unreachable]; + drop(_1) -> [return: bb4, unwind unreachable]; } - bb5: { + bb4: { return; } - bb6: { - StorageDead(_6); + bb5: { StorageDead(_5); - StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; + drop(_3) -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { StorageDead(_3); - drop(_1) -> [return: bb8, unwind unreachable]; + drop(_1) -> [return: bb7, unwind unreachable]; } - bb8: { + bb7: { coroutine_drop; } } diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 14e1782b86016..a77a9c9a96341 100644 --- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -6,11 +6,9 @@ yields () let mut _0: (); let _3: Foo; let _5: (); - let mut _6: (); - let _7: (); - let mut _8: Foo; - let _9: (); - let mut _10: Bar; + let _6: (); + let mut _7: Foo; + let _8: (); scope 1 { debug a => _3; let _4: Bar; @@ -22,97 +20,73 @@ yields () bb0: { StorageLive(_3); _3 = Foo(const 5_i32); - StorageLive(_4); _4 = Bar(const 6_i32); StorageLive(_5); - StorageLive(_6); - _6 = (); - _5 = yield(move _6) -> [resume: bb1, drop: bb6]; + _5 = yield(const ()) -> [resume: bb1, drop: bb5]; } bb1: { - StorageDead(_6); StorageDead(_5); + StorageLive(_6); StorageLive(_7); - StorageLive(_8); - _8 = move _3; - _7 = take::(move _8) -> [return: bb2, unwind: bb10]; + _7 = move _3; + _6 = take::(move _7) -> [return: bb2, unwind: bb9]; } bb2: { - StorageDead(_8); StorageDead(_7); - StorageLive(_9); - StorageLive(_10); - _10 = move _4; - _9 = take::(move _10) -> [return: bb3, unwind: bb9]; + StorageDead(_6); + StorageLive(_8); + _8 = take::(move _4) -> [return: bb3, unwind: bb8]; } bb3: { - StorageDead(_10); - StorageDead(_9); + StorageDead(_8); _0 = const (); - StorageDead(_4); - goto -> bb4; - } - - bb4: { StorageDead(_3); - drop(_1) -> [return: bb5, unwind: bb14]; + drop(_1) -> [return: bb4, unwind continue]; } - bb5: { + bb4: { return; } - bb6: { - StorageDead(_6); + bb5: { StorageDead(_5); - StorageDead(_4); - drop(_3) -> [return: bb7, unwind: bb15]; + drop(_3) -> [return: bb6, unwind: bb12]; } - bb7: { + bb6: { StorageDead(_3); - drop(_1) -> [return: bb8, unwind: bb14]; + drop(_1) -> [return: bb7, unwind continue]; } - bb8: { + bb7: { coroutine_drop; } - bb9 (cleanup): { - StorageDead(_10); - StorageDead(_9); - goto -> bb12; - } - - bb10 (cleanup): { - goto -> bb11; - } - - bb11 (cleanup): { + bb8 (cleanup): { StorageDead(_8); - StorageDead(_7); - goto -> bb12; + goto -> bb10; } - bb12 (cleanup): { - StorageDead(_4); - goto -> bb13; + bb9 (cleanup): { + StorageDead(_7); + StorageDead(_6); + goto -> bb10; } - bb13 (cleanup): { + bb10 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + drop(_1) -> [return: bb11, unwind terminate(cleanup)]; } - bb14 (cleanup): { + bb11 (cleanup): { resume; } - bb15 (cleanup): { + bb12 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + drop(_1) -> [return: bb11, unwind terminate(cleanup)]; } } diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 222c7144ef07d..f37c3f4a5ea05 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -25,61 +25,49 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} debug _x => _2; let mut _0: std::ops::CoroutineState<(), ()>; let _3: HasDrop; - let mut _4: !; - let mut _5: (); - let _6: u8; - let mut _7: (); - let _8: (); - let mut _9: (); - let mut _10: u32; - let mut _11: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}; + let _4: u8; + let _5: (); + let mut _6: (); + let mut _7: u32; + let mut _8: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}; scope 1 { - debug _d => (((*_11) as variant#3).0: HasDrop); + debug _d => (((*_8) as variant#3).0: HasDrop); } bb0: { - _11 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}); - _10 = discriminant((*_11)); - switchInt(move _10) -> [0: bb1, 3: bb5, otherwise: bb6]; + _8 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}); + _7 = discriminant((*_8)); + switchInt(move _7) -> [0: bb1, 3: bb5, otherwise: bb6]; } bb1: { nop; - (((*_11) as variant#3).0: HasDrop) = HasDrop; - StorageLive(_4); + (((*_8) as variant#3).0: HasDrop) = const HasDrop; goto -> bb2; } bb2: { - StorageLive(_6); - StorageLive(_7); - _7 = (); - _0 = CoroutineState::<(), ()>::Yielded(move _7); + StorageLive(_4); + _0 = CoroutineState::<(), ()>::Yielded(const ()); StorageDead(_4); - StorageDead(_6); - StorageDead(_7); - discriminant((*_11)) = 3; + discriminant((*_8)) = 3; return; } bb3: { - StorageDead(_7); - StorageDead(_6); - StorageLive(_8); - _8 = callee() -> [return: bb4, unwind unreachable]; + StorageDead(_4); + StorageLive(_5); + _5 = callee() -> [return: bb4, unwind unreachable]; } bb4: { - StorageDead(_8); - _5 = const (); + StorageDead(_5); goto -> bb2; } bb5: { StorageLive(_4); - StorageLive(_6); - StorageLive(_7); - _6 = move _2; + _4 = move _2; goto -> bb3; } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 151580da19e09..571bcc31e222d 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -23,6 +23,7 @@ + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; ++ let mut _9: bool; + } bb0: { @@ -39,6 +40,7 @@ + _5 = const false; + StorageLive(_6); + StorageLive(_7); ++ StorageLive(_9); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; @@ -56,6 +58,7 @@ bb2: { - StorageDead(_3); - _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; ++ StorageDead(_9); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); @@ -97,8 +100,9 @@ + + bb8: { + StorageLive(_8); ++ _9 = move _5; + StorageDead(_8); -+ _1 = CoroutineState::::Complete(copy _5); ++ _1 = CoroutineState::::Complete(move _9); + discriminant((*_6)) = 1; + goto -> bb2; + } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 6196fc0d0c6bf..33751862f7c92 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -23,6 +23,7 @@ + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; ++ let mut _9: bool; + } bb0: { @@ -39,6 +40,7 @@ + _5 = const false; + StorageLive(_6); + StorageLive(_7); ++ StorageLive(_9); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; @@ -72,6 +74,7 @@ - _0 = const (); - StorageDead(_1); - return; ++ StorageDead(_9); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); @@ -111,8 +114,9 @@ + + bb10: { + StorageLive(_8); ++ _9 = move _5; + StorageDead(_8); -+ _1 = CoroutineState::::Complete(copy _5); ++ _1 = CoroutineState::::Complete(move _9); + discriminant((*_6)) = 1; + goto -> bb4; + } diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.rs b/tests/ui/async-await/future-sizes/async-awaiting-fut.rs index 7113f591630d1..550496be8c100 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.rs +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.rs @@ -5,7 +5,7 @@ //@ edition:2021 //@ build-pass //@ ignore-pass -//@ only-x86_64 +//@ only-64bit async fn wait() {} diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout index b30c15bcbe6ed..a1056edd9c914 100644 --- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout +++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout @@ -1,35 +1,32 @@ -print-type-size type: `{async fn body of test()}`: 3078 bytes, alignment: 1 bytes +print-type-size type: `{async fn body of test()}`: 3079 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes -print-type-size variant `Suspend0`: 3077 bytes -print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()} +print-type-size variant `Suspend0`: 3078 bytes +print-type-size local `.__awaitee`: 3078 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()} print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes -print-type-size field `.value`: 3077 bytes -print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes -print-type-size variant `MaybeUninit`: 3077 bytes +print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3078 bytes, alignment: 1 bytes +print-type-size field `.value`: 3078 bytes +print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3078 bytes, alignment: 1 bytes +print-type-size variant `MaybeUninit`: 3078 bytes print-type-size field `.uninit`: 0 bytes -print-type-size field `.value`: 3077 bytes -print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes +print-type-size field `.value`: 3078 bytes +print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3078 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes -print-type-size variant `Suspend0`: 2052 bytes +print-type-size variant `Suspend0`: 3077 bytes print-type-size upvar `.fut`: 1025 bytes print-type-size local `.fut`: 1025 bytes -print-type-size local `..coroutine_field4`: 1 bytes, type: bool print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} -print-type-size variant `Suspend1`: 3076 bytes +print-type-size padding: 1025 bytes +print-type-size local `..coroutine_field3`: 1 bytes, alignment: 1 bytes, type: bool +print-type-size variant `Suspend1`: 3077 bytes print-type-size upvar `.fut`: 1025 bytes print-type-size padding: 1025 bytes -print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool +print-type-size local `.__awaitee`: 1 bytes, alignment: 1 bytes, type: {async fn body of wait()} print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()} -print-type-size variant `Suspend2`: 2052 bytes -print-type-size upvar `.fut`: 1025 bytes -print-type-size local `.fut`: 1025 bytes -print-type-size local `..coroutine_field4`: 1 bytes, type: bool -print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()} +print-type-size local `..coroutine_field3`: 1 bytes, type: bool print-type-size variant `Returned`: 1025 bytes print-type-size upvar `.fut`: 1025 bytes print-type-size variant `Panicked`: 1025 bytes @@ -68,6 +65,8 @@ print-type-size type: `std::panic::AssertUnwindSafe`: 16 bytes, alignment: 8 bytes print-type-size field `.pointer`: 16 bytes +print-type-size type: `std::future::ResumeTy`: 8 bytes, alignment: 8 bytes +print-type-size field `.0`: 8 bytes print-type-size type: `std::pin::Pin<&mut {async fn body of big_fut()}>`: 8 bytes, alignment: 8 bytes print-type-size field `.pointer`: 8 bytes print-type-size type: `std::pin::Pin<&mut {async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 8 bytes, alignment: 8 bytes @@ -81,6 +80,8 @@ print-type-size field `._vtable_ptr`: 8 bytes print-type-size field `._phantom`: 0 bytes print-type-size type: `std::ptr::NonNull`: 8 bytes, alignment: 8 bytes print-type-size field `.pointer`: 8 bytes +print-type-size type: `std::ptr::NonNull>`: 8 bytes, alignment: 8 bytes +print-type-size field `.pointer`: 8 bytes print-type-size type: `std::mem::ManuallyDrop`: 1 bytes, alignment: 1 bytes print-type-size field `.value`: 1 bytes print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes diff --git a/tests/ui/coroutine/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs index 0f800de84544d..30ff74534c3c3 100644 --- a/tests/ui/coroutine/size-moved-locals.rs +++ b/tests/ui/coroutine/size-moved-locals.rs @@ -76,5 +76,5 @@ fn main() { assert_eq!(1025, std::mem::size_of_val(&move_before_yield())); assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop())); assert_eq!(2051, std::mem::size_of_val(&overlap_move_points())); - assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y())); + assert_eq!(2050, std::mem::size_of_val(&overlap_x_and_y())); } diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout index 4ce1ce46f6e82..30a9df6f20948 100644 --- a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout +++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout @@ -1,17 +1,7 @@ -print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:13:5: 13:7}`: 8 bytes, alignment: 4 bytes +print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:13:5: 13:7}`: 1 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes -print-type-size variant `Suspend0`: 7 bytes -print-type-size padding: 3 bytes -print-type-size local `.w`: 4 bytes, alignment: 4 bytes -print-type-size variant `Suspend1`: 7 bytes -print-type-size padding: 3 bytes -print-type-size local `.z`: 4 bytes, alignment: 4 bytes +print-type-size variant `Suspend0`: 0 bytes +print-type-size variant `Suspend1`: 0 bytes print-type-size variant `Returned`: 0 bytes print-type-size variant `Panicked`: 0 bytes -print-type-size type: `std::mem::ManuallyDrop`: 4 bytes, alignment: 4 bytes -print-type-size field `.value`: 4 bytes -print-type-size type: `std::mem::MaybeUninit`: 4 bytes, alignment: 4 bytes -print-type-size variant `MaybeUninit`: 4 bytes -print-type-size field `.uninit`: 0 bytes -print-type-size field `.value`: 4 bytes diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index 3ec816b657f45..b9d15e066776f 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -48,7 +48,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); - switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3]; + switchInt(move _6) -> [0: bb1, 1: bb4, otherwise: bb5]; } bb1: { StorageLive(_3); @@ -56,14 +56,20 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo _3 = (*_4); _5 = (); StorageDead(_3); + goto -> bb3; + } + bb2: { _0 = std::task::Poll::Ready(move _5); discriminant((*_7)) = 1; return; } - bb2: { - assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; - } bb3: { + goto -> bb2; + } + bb4: { + assert(false, `async fn` resumed after completion) -> [success: bb4, unwind unreachable]; + } + bb5: { unreachable; } } @@ -80,7 +86,7 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); - switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3]; + switchInt(move _6) -> [0: bb1, 1: bb4, otherwise: bb5]; } bb1: { StorageLive(_3); @@ -88,14 +94,20 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c _3 = (*_4); _5 = (); StorageDead(_3); + goto -> bb3; + } + bb2: { _0 = std::task::Poll::Ready(move _5); discriminant((*_7)) = 1; return; } - bb2: { - assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; - } bb3: { + goto -> bb2; + } + bb4: { + assert(false, `async fn` resumed after completion) -> [success: bb4, unwind unreachable]; + } + bb5: { unreachable; } } From 4d758cc01e3a7df52ef948d58bc1b6fedd33ed20 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 14 Sep 2025 21:11:47 +0000 Subject: [PATCH 6/7] Simplify transformed body. --- compiler/rustc_mir_transform/src/coroutine.rs | 25 ++++--- compiler/rustc_mir_transform/src/lib.rs | 8 +- compiler/rustc_mir_transform/src/simplify.rs | 6 ++ ...await.a-{closure#0}.coroutine_resume.0.mir | 30 ++++++-- ...await.b-{closure#0}.coroutine_resume.0.mir | 73 +++++++++++++++++-- ....main-{closure#0}.StateTransform.after.mir | 50 +++++-------- ....main-{closure#1}.StateTransform.after.mir | 50 +++++-------- ...ny.main-{closure#0}.coroutine_resume.0.mir | 42 ++++++++++- .../async-closure.stdout | 28 ++----- 9 files changed, 200 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index b9fd1cabdea15..112d9f94b00ee 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1332,16 +1332,6 @@ fn create_coroutine_resume_function<'tcx>( make_coroutine_state_argument_indirect(tcx, body); } } - - // Make sure we remove dead blocks to remove - // unrelated code from the drop part of the function - simplify::remove_dead_blocks(body); - - pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); - - if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) { - dumper.dump_mir(body); - } } /// An operation that can be performed on a coroutine. @@ -1697,6 +1687,21 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // Create the Coroutine::resume / Future::poll function create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) { + dumper.dump_mir(body); + } + + pm::run_passes_no_validate( + tcx, + body, + &[ + &crate::abort_unwinding_calls::AbortUnwindingCalls, + &crate::simplify::SimplifyCfg::PostStateTransform, + &crate::simplify::SimplifyLocals::PostStateTransform, + ], + None, + ); + // Run derefer to fix Derefs that are not in the first place deref_finder(tcx, body, false); } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ae0b90e928e79..2286afd1681fa 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -81,7 +81,7 @@ mod ssa; macro_rules! declare_passes { ( $( - $vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?; + $vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* $(,)? } )?),+ $(,)?; )* ) => { $( @@ -181,12 +181,14 @@ declare_passes! { PreOptimizations, Final, MakeShim, - AfterUnreachableEnumBranching + AfterUnreachableEnumBranching, + PostStateTransform, }, SimplifyLocals { BeforeConstProp, AfterGVN, - Final + Final, + PostStateTransform, }; mod simplify_branches : SimplifyConstCondition { AfterConstProp, diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index da31600e8324c..1efa1784d2f1c 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -57,6 +57,8 @@ pub(super) enum SimplifyCfg { Final, MakeShim, AfterUnreachableEnumBranching, + /// Extra run introduced by `StateTransform`. + PostStateTransform, } impl SimplifyCfg { @@ -72,6 +74,7 @@ impl SimplifyCfg { SimplifyCfg::AfterUnreachableEnumBranching => { "SimplifyCfg-after-unreachable-enum-branching" } + SimplifyCfg::PostStateTransform => "SimplifyCfg-post-StateTransform", } } } @@ -416,6 +419,8 @@ pub(super) enum SimplifyLocals { BeforeConstProp, AfterGVN, Final, + /// Extra run introduced by `StateTransform`. + PostStateTransform, } impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { @@ -424,6 +429,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop", SimplifyLocals::AfterGVN => "SimplifyLocals-after-value-numbering", SimplifyLocals::Final => "SimplifyLocals-final", + SimplifyLocals::PostStateTransform => "SimplifyLocals-post-StateTransform", } } diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir index 6cad5b105d3e3..f2be506e36885 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -19,12 +19,12 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> bb0: { _5 = copy (_1.0: &mut {async fn body of a()}); _4 = discriminant((*_5)); - switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5]; + switchInt(move _4) -> [0: bb1, 1: bb9, otherwise: bb10]; } bb1: { _3 = const (); - goto -> bb3; + goto -> bb6; } bb2: { @@ -34,14 +34,34 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> } bb3: { - goto -> bb2; + return; } bb4: { - assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind unreachable]; + goto -> bb8; + } + + bb5 (cleanup): { + unreachable; + } + + bb6: { + goto -> bb2; + } + + bb7 (cleanup): { + resume; + } + + bb8: { + goto -> bb3; + } + + bb9: { + assert(const false, "`async fn` resumed after completion") -> [success: bb9, unwind continue]; } - bb5: { + bb10: { unreachable; } } diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 7cf9c28664c23..775371863fbe2 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -105,7 +105,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb0: { _39 = copy (_1.0: &mut {async fn body of b()}); _38 = discriminant((*_39)); - switchInt(move _38) -> [0: bb1, 1: bb27, 3: bb25, 4: bb26, otherwise: bb8]; + switchInt(move _38) -> [0: bb1, 1: bb39, 3: bb37, 4: bb38, otherwise: bb40]; } bb1: { @@ -296,7 +296,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb22: { nop; StorageDead(_21); - goto -> bb24; + goto -> bb33; } bb23: { @@ -306,10 +306,67 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> } bb24: { - goto -> bb23; + StorageDead(_36); + StorageDead(_35); + drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb25, unwind unreachable]; } bb25: { + nop; + StorageDead(_21); + goto -> bb28; + } + + bb26: { + StorageDead(_20); + StorageDead(_19); + drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb27, unwind unreachable]; + } + + bb27: { + nop; + StorageDead(_4); + StorageDead(_3); + goto -> bb28; + } + + bb28: { + goto -> bb34; + } + + bb29: { + coroutine_drop; + } + + bb30: { + return; + } + + bb31: { + goto -> bb36; + } + + bb32 (cleanup): { + unreachable; + } + + bb33: { + goto -> bb23; + } + + bb34: { + goto -> bb29; + } + + bb35 (cleanup): { + resume; + } + + bb36: { + goto -> bb30; + } + + bb37: { StorageLive(_3); StorageLive(_4); StorageLive(_19); @@ -318,7 +375,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> goto -> bb11; } - bb26: { + bb38: { StorageLive(_21); StorageLive(_35); StorageLive(_36); @@ -326,7 +383,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> goto -> bb21; } - bb27: { - assert(const false, "`async fn` resumed after completion") -> [success: bb27, unwind unreachable]; + bb39: { + assert(const false, "`async fn` resumed after completion") -> [success: bb39, unwind continue]; + } + + bb40: { + unreachable; } } diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir index 428d29fc518ad..f5005bb872d28 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir @@ -45,7 +45,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb0: { _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16]; + switchInt(move _17) -> [0: bb1, 1: bb11, 3: bb9, 4: bb10, otherwise: bb12]; } bb1: { @@ -76,11 +76,6 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 } bb4: { - StorageDead(_4); - drop(_3) -> [return: bb5, unwind unreachable]; - } - - bb5: { StorageDead(_3); StorageLive(_8); StorageLive(_9); @@ -91,17 +86,17 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageLive(_12); StorageLive(_13); _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb6, unwind unreachable]; + _12 = ::clone(move _13) -> [return: bb5, unwind unreachable]; } - bb6: { + bb5: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { _14 = &(*_15); _9 = (move _10, move _12, move _14); StorageDead(_14); @@ -116,54 +111,43 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 return; } - bb8: { - StorageDead(_9); - drop(_8) -> [return: bb9, unwind unreachable]; - } - - bb9: { + bb7: { StorageDead(_15); StorageDead(_11); StorageDead(_8); _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb8, unwind unreachable]; } - bb10: { - goto -> bb12; - } - - bb11: { + bb8: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); discriminant((*_18)) = 1; return; } - bb12: { - goto -> bb11; - } - - bb13: { + bb9: { StorageLive(_3); StorageLive(_4); _3 = move _2; - goto -> bb4; + StorageDead(_4); + drop(_3) -> [return: bb4, unwind unreachable]; } - bb14: { + bb10: { StorageLive(_8); StorageLive(_9); StorageLive(_11); StorageLive(_15); _8 = move _2; - goto -> bb8; + StorageDead(_9); + drop(_8) -> [return: bb7, unwind unreachable]; } - bb15: { - assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable]; + bb11: { + assert(const false, "coroutine resumed after completion") -> [success: bb11, unwind unreachable]; } - bb16: { + bb12: { unreachable; } } diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir index 23d0afa337deb..50dff91275b80 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir @@ -45,7 +45,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb0: { _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb15, 3: bb13, 4: bb14, otherwise: bb16]; + switchInt(move _17) -> [0: bb1, 1: bb11, 3: bb9, 4: bb10, otherwise: bb12]; } bb1: { @@ -76,11 +76,6 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 } bb4: { - StorageDead(_4); - drop(_3) -> [return: bb5, unwind unreachable]; - } - - bb5: { StorageDead(_3); StorageLive(_8); StorageLive(_9); @@ -91,17 +86,17 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageLive(_12); StorageLive(_13); _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb6, unwind unreachable]; + _12 = ::clone(move _13) -> [return: bb5, unwind unreachable]; } - bb6: { + bb5: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb7, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { _14 = &(*_15); _9 = (move _10, move _12, move _14); StorageDead(_14); @@ -116,54 +111,43 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 return; } - bb8: { - StorageDead(_9); - drop(_8) -> [return: bb9, unwind unreachable]; - } - - bb9: { + bb7: { StorageDead(_15); StorageDead(_11); StorageDead(_8); _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb10, unwind unreachable]; + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb8, unwind unreachable]; } - bb10: { - goto -> bb12; - } - - bb11: { + bb8: { _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); discriminant((*_18)) = 1; return; } - bb12: { - goto -> bb11; - } - - bb13: { + bb9: { StorageLive(_3); StorageLive(_4); _3 = move _2; - goto -> bb4; + StorageDead(_4); + drop(_3) -> [return: bb4, unwind unreachable]; } - bb14: { + bb10: { StorageLive(_8); StorageLive(_9); StorageLive(_11); StorageLive(_15); _8 = move _2; - goto -> bb8; + StorageDead(_9); + drop(_8) -> [return: bb7, unwind unreachable]; } - bb15: { - assert(const false, "coroutine resumed after completion") -> [success: bb15, unwind unreachable]; + bb11: { + assert(const false, "coroutine resumed after completion") -> [success: bb11, unwind unreachable]; } - bb16: { + bb12: { unreachable; } } diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index f37c3f4a5ea05..71425740581c2 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -37,7 +37,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} bb0: { _8 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}); _7 = discriminant((*_8)); - switchInt(move _7) -> [0: bb1, 3: bb5, otherwise: bb6]; + switchInt(move _7) -> [0: bb1, 3: bb14, otherwise: bb15]; } bb1: { @@ -66,12 +66,50 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} } bb5: { + StorageDead(_4); + drop((((*_8) as variant#3).0: HasDrop)) -> [return: bb6, unwind unreachable]; + } + + bb6: { + nop; + goto -> bb11; + } + + bb7: { + coroutine_drop; + } + + bb8: { + return; + } + + bb9: { + goto -> bb13; + } + + bb10 (cleanup): { + unreachable; + } + + bb11: { + goto -> bb7; + } + + bb12 (cleanup): { + resume; + } + + bb13: { + goto -> bb8; + } + + bb14: { StorageLive(_4); _4 = move _2; goto -> bb3; } - bb6: { + bb15: { unreachable; } } diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index b9d15e066776f..3ec816b657f45 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -48,7 +48,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); - switchInt(move _6) -> [0: bb1, 1: bb4, otherwise: bb5]; + switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3]; } bb1: { StorageLive(_3); @@ -56,20 +56,14 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo _3 = (*_4); _5 = (); StorageDead(_3); - goto -> bb3; - } - bb2: { _0 = std::task::Poll::Ready(move _5); discriminant((*_7)) = 1; return; } - bb3: { - goto -> bb2; - } - bb4: { - assert(false, `async fn` resumed after completion) -> [success: bb4, unwind unreachable]; + bb2: { + assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; } - bb5: { + bb3: { unreachable; } } @@ -86,7 +80,7 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c bb0: { _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); - switchInt(move _6) -> [0: bb1, 1: bb4, otherwise: bb5]; + switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3]; } bb1: { StorageLive(_3); @@ -94,20 +88,14 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c _3 = (*_4); _5 = (); StorageDead(_3); - goto -> bb3; - } - bb2: { _0 = std::task::Poll::Ready(move _5); discriminant((*_7)) = 1; return; } - bb3: { - goto -> bb2; - } - bb4: { - assert(false, `async fn` resumed after completion) -> [success: bb4, unwind unreachable]; + bb2: { + assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; } - bb5: { + bb3: { unreachable; } } From 0af6ba66c1683a55fdabcc06704e374e1a5e885f Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Thu, 9 Oct 2025 12:21:06 +0000 Subject: [PATCH 7/7] FIXME Remove crash test. --- tests/crashes/140303.rs | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 tests/crashes/140303.rs diff --git a/tests/crashes/140303.rs b/tests/crashes/140303.rs deleted file mode 100644 index 43a20b5e58ed4..0000000000000 --- a/tests/crashes/140303.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ known-bug: #140303 -//@compile-flags: -Zvalidate-mir -use std::future::Future; -async fn a() -> impl Sized { - b(c) -} -async fn c(); // kaboom -fn b(e: d) -> impl Sized -where - d: f, -{ - || -> ::h { panic!() } -} -trait f { - type h; -} -impl f for d -where - d: Fn() -> g, - g: Future, -{ -}