From 5878c571846eea48d999b1b27c43eeab2e5b6fd5 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 10 May 2026 14:29:19 +0000 Subject: [PATCH 1/5] Make a dedicated coroutine mir-opt test directory. --- tests/mir-opt/building/async_await.rs | 18 --- ...await.a-{closure#0}.coroutine_resume.0.mir | 2 +- ...await.b-{closure#0}.coroutine_resume.0.mir | 134 +++++++++++++++--- tests/mir-opt/coroutine/async_await.rs | 29 ++++ ...oo-{closure#0}-{closure#0}.built.after.mir | 0 ...-{closure#0}-{synthetic#0}.built.after.mir | 0 .../async_closure_fake_read_for_by_move.rs | 0 ...0}-{closure#0}-{closure#0}.built.after.mir | 0 ...-{closure#0}-{synthetic#0}.built.after.mir | 0 ...closure#0}.coroutine_closure_by_move.0.mir | 0 ...0}-{closure#1}-{closure#0}.built.after.mir | 0 ...-{closure#1}-{synthetic#0}.built.after.mir | 0 ...closure#1}.coroutine_closure_by_move.0.mir | 0 ...{closure#1}.coroutine_closure_by_ref.0.mir | 0 .../{ => coroutine}/async_closure_shims.rs | 0 ...#0}.coroutine_drop_async.0.panic-abort.mir | 0 ...0}.coroutine_drop_async.0.panic-unwind.mir | 0 .../{ => coroutine}/async_drop_live_dead.rs | 0 ...losure#0}.[Foo;1].MentionedItems.after.mir | 0 .../{ => coroutine}/async_drop_mir_pin.rs | 0 ....main-{closure#0}.StateTransform.after.mir | 119 +++++++++++++--- ....main-{closure#1}.StateTransform.after.mir | 119 +++++++++++++--- .../{building => coroutine}/coroutine.rs | 3 +- ...losure#0}.coroutine_drop.0.panic-abort.mir | 0 ...osure#0}.coroutine_drop.0.panic-unwind.mir | 0 .../{ => coroutine}/coroutine_drop_cleanup.rs | 0 ...e#0}.StateTransform.before.panic-abort.mir | 0 ...#0}.StateTransform.before.panic-unwind.mir | 0 .../coroutine_storage_dead_unwind.rs | 0 ...ny.main-{closure#0}.coroutine_resume.0.mir | 0 .../mir-opt/{ => coroutine}/coroutine_tiny.rs | 0 .../{ => inline}/inline_coroutine_body.rs | 0 ...y.run2-{closure#0}.Inline.panic-abort.diff | 0 ....run2-{closure#0}.Inline.panic-unwind.diff | 0 34 files changed, 347 insertions(+), 77 deletions(-) delete mode 100644 tests/mir-opt/building/async_await.rs rename tests/mir-opt/{building => coroutine}/async_await.a-{closure#0}.coroutine_resume.0.mir (96%) rename tests/mir-opt/{building => coroutine}/async_await.b-{closure#0}.coroutine_resume.0.mir (75%) create mode 100644 tests/mir-opt/coroutine/async_await.rs rename tests/mir-opt/{ => coroutine}/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_fake_read_for_by_move.rs (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir (100%) rename tests/mir-opt/{ => coroutine}/async_closure_shims.rs (100%) rename tests/mir-opt/{ => coroutine}/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir (100%) rename tests/mir-opt/{ => coroutine}/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir (100%) rename tests/mir-opt/{ => coroutine}/async_drop_live_dead.rs (100%) rename tests/mir-opt/{ => coroutine}/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir (100%) rename tests/mir-opt/{ => coroutine}/async_drop_mir_pin.rs (100%) rename tests/mir-opt/{building => coroutine}/coroutine.main-{closure#0}.StateTransform.after.mir (64%) rename tests/mir-opt/{building => coroutine}/coroutine.main-{closure#1}.StateTransform.after.mir (64%) rename tests/mir-opt/{building => coroutine}/coroutine.rs (93%) rename tests/mir-opt/{ => coroutine}/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir (100%) rename tests/mir-opt/{ => coroutine}/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir (100%) rename tests/mir-opt/{ => coroutine}/coroutine_drop_cleanup.rs (100%) rename tests/mir-opt/{ => coroutine}/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir (100%) rename tests/mir-opt/{ => coroutine}/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir (100%) rename tests/mir-opt/{ => coroutine}/coroutine_storage_dead_unwind.rs (100%) rename tests/mir-opt/{ => coroutine}/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir (100%) rename tests/mir-opt/{ => coroutine}/coroutine_tiny.rs (100%) rename tests/mir-opt/{ => inline}/inline_coroutine_body.rs (100%) rename tests/mir-opt/{ => inline}/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff (100%) rename tests/mir-opt/{ => inline}/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff (100%) diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs deleted file mode 100644 index e84f8a6c561bc..0000000000000 --- a/tests/mir-opt/building/async_await.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ skip-filecheck -// This test makes sure that the coroutine MIR pass eliminates all calls to -// `get_context`, and that the MIR argument type for an async fn and all locals -// related to `yield` are `&mut Context`, and its return type is `Poll`. - -//@ edition:2018 -//@ compile-flags: -Zmir-opt-level=0 -C panic=abort - -#![crate_type = "lib"] - -// EMIT_MIR async_await.a-{closure#0}.coroutine_resume.0.mir -async fn a() {} - -// EMIT_MIR async_await.b-{closure#0}.coroutine_resume.0.mir -pub async fn b() { - a().await; - a().await -} diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir similarity index 96% rename from tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir rename to tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir index 6cad5b105d3e3..f59cdb5c27bc0 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -38,7 +38,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> } bb4: { - assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind unreachable]; + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; } bb5: { diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir similarity index 75% rename from tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir rename to tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir index 96ee37185db16..0c130634aeac4 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -13,7 +13,7 @@ ], ), source_info: SourceInfo { - span: $DIR/async_await.rs:16:5: 16:14 (#9), + span: $DIR/async_await.rs:27:5: 27:14 (#9), scope: scope[0], }, ignore_for_traits: false, @@ -30,7 +30,7 @@ ], ), source_info: SourceInfo { - span: $DIR/async_await.rs:17:5: 17:14 (#11), + span: $DIR/async_await.rs:28:5: 28:14 (#11), scope: scope[0], }, ignore_for_traits: false, @@ -105,18 +105,18 @@ 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: bb47, 2: bb46, 3: bb44, 4: bb45, otherwise: bb8]; } bb1: { StorageLive(_3); StorageLive(_4); StorageLive(_5); - _5 = a() -> [return: bb2, unwind unreachable]; + _5 = a() -> [return: bb2, unwind: bb38]; } bb2: { - _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; + _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind: bb37]; } bb3: { @@ -135,7 +135,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_12); _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]; + _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind: bb34]; } bb5: { @@ -151,7 +151,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb6: { _13 = &mut (*_14); StorageDead(_15); - _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; + _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind: bb33]; } bb7: { @@ -193,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((((*_39) 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: bb36]; } bb11: { @@ -214,11 +214,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_3); StorageLive(_21); StorageLive(_22); - _22 = a() -> [return: bb14, unwind unreachable]; + _22 = a() -> [return: bb14, unwind: bb31]; } bb14: { - _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind: bb30]; } bb15: { @@ -237,7 +237,7 @@ 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: bb17, unwind: bb27]; } bb17: { @@ -253,7 +253,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb18: { _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: bb19, unwind: bb26]; } bb19: { @@ -290,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((((*_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: bb23, unwind: bb29]; } bb22: { @@ -308,7 +308,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb24: { StorageDead(_21); - goto -> bb26; + goto -> bb42; } bb25: { @@ -317,11 +317,103 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> return; } - bb26: { + bb26 (cleanup): { + StorageDead(_29); + StorageDead(_26); + StorageDead(_30); + goto -> bb28; + } + + bb27 (cleanup): { + StorageDead(_27); + StorageDead(_26); + goto -> bb28; + } + + bb28 (cleanup): { + StorageDead(_28); + StorageDead(_25); + StorageDead(_24); + drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb29, unwind terminate(cleanup)]; + } + + bb29 (cleanup): { + nop; + goto -> bb32; + } + + bb30 (cleanup): { + goto -> bb31; + } + + bb31 (cleanup): { + StorageDead(_22); + goto -> bb32; + } + + bb32 (cleanup): { + StorageDead(_21); + goto -> bb40; + } + + bb33 (cleanup): { + StorageDead(_13); + StorageDead(_10); + StorageDead(_14); + goto -> bb35; + } + + bb34 (cleanup): { + StorageDead(_11); + StorageDead(_10); + goto -> bb35; + } + + bb35 (cleanup): { + StorageDead(_12); + StorageDead(_9); + StorageDead(_8); + drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb36, unwind terminate(cleanup)]; + } + + bb36 (cleanup): { + nop; + goto -> bb39; + } + + bb37 (cleanup): { + goto -> bb38; + } + + bb38 (cleanup): { + StorageDead(_5); + goto -> bb39; + } + + bb39 (cleanup): { + StorageDead(_4); + StorageDead(_3); + goto -> bb40; + } + + bb40 (cleanup): { + goto -> bb41; + } + + bb41 (cleanup): { + goto -> bb43; + } + + bb42: { goto -> bb25; } - bb27: { + bb43 (cleanup): { + discriminant((*_39)) = 2; + resume; + } + + bb44: { StorageLive(_3); StorageLive(_4); StorageLive(_19); @@ -330,7 +422,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> goto -> bb11; } - bb28: { + bb45: { StorageLive(_21); StorageLive(_35); StorageLive(_36); @@ -338,7 +430,11 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> goto -> bb22; } - bb29: { - assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; + bb46: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb46, unwind continue]; + } + + bb47: { + assert(const false, "`async fn` resumed after completion") -> [success: bb47, unwind continue]; } } diff --git a/tests/mir-opt/coroutine/async_await.rs b/tests/mir-opt/coroutine/async_await.rs new file mode 100644 index 0000000000000..8334baa594720 --- /dev/null +++ b/tests/mir-opt/coroutine/async_await.rs @@ -0,0 +1,29 @@ +// This test makes sure that the coroutine MIR pass eliminates all calls to +// `get_context`, and that the MIR argument type for an async fn and all locals +// related to `yield` are `&mut Context`, and its return type is `Poll`. + +//@ edition:2018 +//@ compile-flags: -Zmir-opt-level=0 +//@ needs-unwind + +#![crate_type = "lib"] + +// EMIT_MIR async_await.a-{closure#0}.coroutine_resume.0.mir +async fn a() { + // CHECK-LABEL: fn a::{closure#0}( + // CHECK-SAME: _1: Pin<&mut {async fn body of a()}> + // CHECK-SAME: _2: &mut Context<'_> + // CHECK-SAME: -> Poll<()> + // CHECK-NOT: get_context +} + +// EMIT_MIR async_await.b-{closure#0}.coroutine_resume.0.mir +pub async fn b() { + // CHECK-LABEL: fn b::{closure#0}( + // CHECK-SAME: _1: Pin<&mut {async fn body of b()}> + // CHECK-SAME: _2: &mut Context<'_> + // CHECK-SAME: -> Poll<()> + // CHECK-NOT: get_context + a().await; + a().await +} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.rs rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/coroutine/async_closure_shims.rs similarity index 100% rename from tests/mir-opt/async_closure_shims.rs rename to tests/mir-opt/coroutine/async_closure_shims.rs diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir similarity index 100% rename from tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir rename to tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir similarity index 100% rename from tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir rename to tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir diff --git a/tests/mir-opt/async_drop_live_dead.rs b/tests/mir-opt/coroutine/async_drop_live_dead.rs similarity index 100% rename from tests/mir-opt/async_drop_live_dead.rs rename to tests/mir-opt/coroutine/async_drop_live_dead.rs diff --git a/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir similarity index 100% rename from tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir rename to tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir diff --git a/tests/mir-opt/async_drop_mir_pin.rs b/tests/mir-opt/coroutine/async_drop_mir_pin.rs similarity index 100% rename from tests/mir-opt/async_drop_mir_pin.rs rename to tests/mir-opt/coroutine/async_drop_mir_pin.rs diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir similarity index 64% rename from tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir rename to tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir index b61215dc28cb4..7adceef744a2a 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir @@ -4,7 +4,7 @@ _s0: CoroutineSavedTy { ty: std::string::String, source_info: SourceInfo { - span: $DIR/coroutine.rs:18:6: 18:9 (#0), + span: $DIR/coroutine.rs:19:6: 19:9 (#0), scope: scope[0], }, ignore_for_traits: false, @@ -22,7 +22,7 @@ }, } */ -fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { +fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { 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; @@ -40,12 +40,12 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 let _15: &std::panic::Location<'_>; let mut _16: (); let mut _17: u32; - let mut _18: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}; + let mut _18: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}; bb0: { - _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}); + _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}); _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20]; + switchInt(move _17) -> [0: bb1, 1: bb35, 2: bb34, 3: bb32, 4: bb33, otherwise: bb36]; } bb1: { @@ -55,13 +55,13 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageLive(_5); StorageLive(_6); _6 = &(((*_18) as variant#4).0: std::string::String); - _5 = ::clone(move _6) -> [return: bb2, unwind unreachable]; + _5 = ::clone(move _6) -> [return: bb2, unwind: bb23]; } bb2: { StorageDead(_6); StorageLive(_7); - _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable]; + _7 = Location::<'_>::caller() -> [return: bb3, unwind: bb22]; } bb3: { @@ -85,7 +85,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb6: { StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; + drop(_3) -> [return: bb7, unwind: bb26]; } bb7: { @@ -99,14 +99,14 @@ 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: bb8, unwind: bb20]; } bb8: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb9, unwind: bb16]; } bb9: { @@ -134,7 +134,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb12: { StorageDead(_9); - drop(_8) -> [return: bb13, unwind unreachable]; + drop(_8) -> [return: bb13, unwind: bb19]; } bb13: { @@ -142,11 +142,11 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 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: bb14, unwind: bb28]; } bb14: { - goto -> bb16; + goto -> bb30; } bb15: { @@ -155,18 +155,95 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 return; } - bb16: { + bb16 (cleanup): { + StorageDead(_14); + drop(_12) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + StorageDead(_12); + StorageDead(_10); + goto -> bb18; + } + + bb18 (cleanup): { + StorageDead(_9); + goto -> bb19; + } + + bb19 (cleanup): { + StorageDead(_15); + goto -> bb21; + } + + bb20 (cleanup): { + StorageDead(_13); + StorageDead(_12); + StorageDead(_10); + StorageDead(_9); + goto -> bb21; + } + + bb21 (cleanup): { + StorageDead(_11); + StorageDead(_8); + goto -> bb27; + } + + bb22 (cleanup): { + StorageDead(_7); + drop(_5) -> [return: bb24, unwind terminate(cleanup)]; + } + + bb23 (cleanup): { + StorageDead(_6); + goto -> bb24; + } + + bb24 (cleanup): { + StorageDead(_5); + goto -> bb25; + } + + bb25 (cleanup): { + StorageDead(_4); + goto -> bb26; + } + + bb26 (cleanup): { + StorageDead(_3); + goto -> bb27; + } + + bb27 (cleanup): { + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb28, unwind terminate(cleanup)]; + } + + bb28 (cleanup): { + goto -> bb29; + } + + bb29 (cleanup): { + goto -> bb31; + } + + bb30: { goto -> bb15; } - bb17: { + bb31 (cleanup): { + discriminant((*_18)) = 2; + resume; + } + + bb32: { StorageLive(_3); StorageLive(_4); _3 = move _2; goto -> bb5; } - bb18: { + bb33: { StorageLive(_8); StorageLive(_9); StorageLive(_11); @@ -175,11 +252,15 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 goto -> bb11; } - bb19: { - assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable]; + bb34: { + assert(const false, "coroutine resumed after panicking") -> [success: bb34, unwind continue]; + } + + bb35: { + assert(const false, "coroutine resumed after completion") -> [success: bb35, unwind continue]; } - bb20: { + bb36: { unreachable; } } diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir similarity index 64% rename from tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir rename to tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir index aac028a9e6c0e..b4fcd2051303e 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir @@ -4,7 +4,7 @@ _s0: CoroutineSavedTy { ty: std::string::String, source_info: SourceInfo { - span: $DIR/coroutine.rs:25:6: 25:9 (#0), + span: $DIR/coroutine.rs:26:6: 26:9 (#0), scope: scope[0], }, ignore_for_traits: false, @@ -22,7 +22,7 @@ }, } */ -fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { +fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { 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; @@ -40,12 +40,12 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 let _15: &std::panic::Location<'_>; let mut _16: (); let mut _17: u32; - let mut _18: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}; + let mut _18: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}; bb0: { - _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}); + _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}); _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20]; + switchInt(move _17) -> [0: bb1, 1: bb35, 2: bb34, 3: bb32, 4: bb33, otherwise: bb36]; } bb1: { @@ -55,13 +55,13 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageLive(_5); StorageLive(_6); _6 = &(((*_18) as variant#4).0: std::string::String); - _5 = ::clone(move _6) -> [return: bb2, unwind unreachable]; + _5 = ::clone(move _6) -> [return: bb2, unwind: bb23]; } bb2: { StorageDead(_6); StorageLive(_7); - _7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable]; + _7 = Location::<'_>::caller() -> [return: bb3, unwind: bb22]; } bb3: { @@ -85,7 +85,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb6: { StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; + drop(_3) -> [return: bb7, unwind: bb26]; } bb7: { @@ -99,14 +99,14 @@ 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: bb8, unwind: bb20]; } bb8: { StorageDead(_13); StorageLive(_14); StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable]; + _15 = Location::<'_>::caller() -> [return: bb9, unwind: bb16]; } bb9: { @@ -134,7 +134,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb12: { StorageDead(_9); - drop(_8) -> [return: bb13, unwind unreachable]; + drop(_8) -> [return: bb13, unwind: bb19]; } bb13: { @@ -142,11 +142,11 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 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: bb14, unwind: bb28]; } bb14: { - goto -> bb16; + goto -> bb30; } bb15: { @@ -155,18 +155,95 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 return; } - bb16: { + bb16 (cleanup): { + StorageDead(_14); + drop(_12) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + StorageDead(_12); + StorageDead(_10); + goto -> bb18; + } + + bb18 (cleanup): { + StorageDead(_9); + goto -> bb19; + } + + bb19 (cleanup): { + StorageDead(_15); + goto -> bb21; + } + + bb20 (cleanup): { + StorageDead(_13); + StorageDead(_12); + StorageDead(_10); + StorageDead(_9); + goto -> bb21; + } + + bb21 (cleanup): { + StorageDead(_11); + StorageDead(_8); + goto -> bb27; + } + + bb22 (cleanup): { + StorageDead(_7); + drop(_5) -> [return: bb24, unwind terminate(cleanup)]; + } + + bb23 (cleanup): { + StorageDead(_6); + goto -> bb24; + } + + bb24 (cleanup): { + StorageDead(_5); + goto -> bb25; + } + + bb25 (cleanup): { + StorageDead(_4); + goto -> bb26; + } + + bb26 (cleanup): { + StorageDead(_3); + goto -> bb27; + } + + bb27 (cleanup): { + drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb28, unwind terminate(cleanup)]; + } + + bb28 (cleanup): { + goto -> bb29; + } + + bb29 (cleanup): { + goto -> bb31; + } + + bb30: { goto -> bb15; } - bb17: { + bb31 (cleanup): { + discriminant((*_18)) = 2; + resume; + } + + bb32: { StorageLive(_3); StorageLive(_4); _3 = move _2; goto -> bb5; } - bb18: { + bb33: { StorageLive(_8); StorageLive(_9); StorageLive(_11); @@ -175,11 +252,15 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 goto -> bb11; } - bb19: { - assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable]; + bb34: { + assert(const false, "coroutine resumed after panicking") -> [success: bb34, unwind continue]; + } + + bb35: { + assert(const false, "coroutine resumed after completion") -> [success: bb35, unwind continue]; } - bb20: { + bb36: { unreachable; } } diff --git a/tests/mir-opt/building/coroutine.rs b/tests/mir-opt/coroutine/coroutine.rs similarity index 93% rename from tests/mir-opt/building/coroutine.rs rename to tests/mir-opt/coroutine/coroutine.rs index 77388c8786aaa..41fdbee119e14 100644 --- a/tests/mir-opt/building/coroutine.rs +++ b/tests/mir-opt/coroutine/coroutine.rs @@ -1,6 +1,7 @@ //@ skip-filecheck //@ edition:2024 -//@ compile-flags: -Zmir-opt-level=0 -C panic=abort +//@ compile-flags: -Zmir-opt-level=0 +//@ needs-unwind #![feature(stmt_expr_attributes)] #![feature(closure_track_caller)] diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine/coroutine_drop_cleanup.rs similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.rs rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.rs diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.rs rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir similarity index 100% rename from tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir rename to tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir diff --git a/tests/mir-opt/coroutine_tiny.rs b/tests/mir-opt/coroutine/coroutine_tiny.rs similarity index 100% rename from tests/mir-opt/coroutine_tiny.rs rename to tests/mir-opt/coroutine/coroutine_tiny.rs diff --git a/tests/mir-opt/inline_coroutine_body.rs b/tests/mir-opt/inline/inline_coroutine_body.rs similarity index 100% rename from tests/mir-opt/inline_coroutine_body.rs rename to tests/mir-opt/inline/inline_coroutine_body.rs diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff similarity index 100% rename from tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff rename to tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff similarity index 100% rename from tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff rename to tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff From d332a1249cf01543ee65284823ba6ecace629ce3 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Thu, 14 May 2026 12:48:24 +0000 Subject: [PATCH 2/5] Change how coroutine layout is dumped in MIR. --- compiler/rustc_middle/src/mir/pretty.rs | 77 ++++++++++++++++++- ...await.a-{closure#0}.coroutine_resume.0.mir | 17 ++-- ...await.b-{closure#0}.coroutine_resume.0.mir | 63 ++++----------- ....main-{closure#0}.StateTransform.after.mir | 34 +++----- ....main-{closure#1}.StateTransform.after.mir | 34 +++----- ...ny.main-{closure#0}.coroutine_resume.0.mir | 32 +++----- 6 files changed, 131 insertions(+), 126 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 60c829311c4b1..1f8efa72ea867 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -15,6 +15,7 @@ use crate::mir::interpret::{ }; use crate::mir::visit::Visitor; use crate::mir::*; +use crate::ty::CoroutineArgsExt; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements @@ -185,9 +186,6 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { Some(promoted) => write!(w, "::{promoted:?}`")?, } writeln!(w, " {} {}", self.disambiguator, self.pass_name)?; - if let Some(ref layout) = body.coroutine_layout_raw() { - writeln!(w, "/* coroutine_layout = {layout:#?} */")?; - } writeln!(w)?; (self.writer.extra_data)(PassWhere::BeforeCFG, w)?; write_user_type_annotations(self.tcx(), body, w)?; @@ -429,6 +427,31 @@ fn write_scope_tree( } } + // Coroutine debuginfo. + if let Some(layout) = body.coroutine_layout_raw() { + for (field, name) in layout.field_names.iter_enumerated() { + if let Some(name) = name + && let source_info = layout.field_tys[field].source_info + && source_info.scope == parent + { + let indented_debug_info = + format!("{0:1$}coroutine debug {2} => {3:?};", INDENT, indent, name, field); + + if options.include_extra_comments { + writeln!( + w, + "{0:1$} // in {2}", + indented_debug_info, + ALIGN, + comment(tcx, source_info), + )?; + } else { + writeln!(w, "{indented_debug_info}")?; + } + } + } + } + // Local variable types. for (local, local_decl) in body.local_decls.iter_enumerated() { if (1..body.arg_count + 1).contains(&local.index()) { @@ -530,6 +553,50 @@ impl Debug for VarDebugInfo<'_> { } } +fn write_coroutine_layout<'tcx>( + tcx: TyCtxt<'tcx>, + layout: &CoroutineLayout<'_>, + w: &mut dyn io::Write, + options: PrettyPrintMirOptions, +) -> io::Result<()> { + let CoroutineLayout { + field_tys, + field_names: _, // Dumped in scope tree with debug info. + variant_fields, + variant_source_info, + storage_conflicts, + } = layout; + + writeln!(w, "{INDENT}coroutine layout {{")?; + + for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits }) in + field_tys.iter_enumerated() + { + let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" }; + let indented_body = format!("{INDENT}{INDENT}field {field:?}: {ty}{ignore_for_traits};",); + if options.include_extra_comments { + writeln!(w, "{0:ALIGN$} // in {1}", indented_body, comment(tcx, *source_info))?; + } else { + writeln!(w, "{}", indented_body)?; + } + } + + writeln!(w, "{INDENT}{INDENT}variant_fields = {{")?; + for (variant, fields) in variant_fields.iter_enumerated() { + let variant_name = ty::CoroutineArgs::variant_name(variant); + let header = format!("{INDENT}{INDENT}{INDENT}{variant_name:9}({variant:?}): {fields:?},"); + if options.include_extra_comments { + let source_info = variant_source_info[variant]; + writeln!(w, "{0:ALIGN$} // in {1}", header, comment(tcx, source_info))?; + } else { + writeln!(w, "{}", header)?; + } + } + writeln!(w, "{INDENT}{INDENT}}}")?; + writeln!(w, "{INDENT}{INDENT}storage_conflicts = {storage_conflicts:?}")?; + writeln!(w, "{INDENT}}}") +} + /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its /// local variables (both user-defined bindings and compiler temporaries). fn write_mir_intro<'tcx>( @@ -541,6 +608,10 @@ fn write_mir_intro<'tcx>( write_mir_sig(tcx, body, w)?; writeln!(w, "{{")?; + if let Some(ref layout) = body.coroutine_layout_raw() { + write_coroutine_layout(tcx, layout, w, options)?; + } + // construct a scope tree and write it out let mut scope_tree: FxHashMap> = Default::default(); for (index, scope_data) in body.source_scopes.iter_enumerated() { diff --git a/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir index f59cdb5c27bc0..539316c9725e4 100644 --- a/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -1,15 +1,14 @@ // MIR for `a::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: {}, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - }, - storage_conflicts: BitMatrix(0x0) {}, -} */ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } debug _task_context => _2; let mut _0: std::task::Poll<()>; let mut _3: (); diff --git a/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir index 0c130634aeac4..22e4a8cee6494 100644 --- a/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -1,56 +1,21 @@ // MIR for `b::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: Coroutine( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [ - (), - std::future::ResumeTy, - (), - (), - (), - ], - ), - source_info: SourceInfo { - span: $DIR/async_await.rs:27:5: 27:14 (#9), - scope: scope[0], - }, - ignore_for_traits: false, - }, - _s1: CoroutineSavedTy { - ty: Coroutine( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [ - (), - std::future::ResumeTy, - (), - (), - (), - ], - ), - source_info: SourceInfo { - span: $DIR/async_await.rs:28:5: 28:14 (#11), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s1], - }, - storage_conflicts: BitMatrix(2x2) { - (_s0, _s0), - (_s1, _s1), - }, -} */ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: {async fn body of a()}; + field _s1: {async fn body of a()}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s1], + } + storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)} + } debug _task_context => _2; + coroutine debug __awaitee => _s0; + coroutine debug __awaitee => _s1; let mut _0: std::task::Poll<()>; let _3: (); let mut _4: {async fn body of a()}; diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir index 7adceef744a2a..60e52d51829fc 100644 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir @@ -1,29 +1,19 @@ // MIR for `main::{closure#0}` after StateTransform -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: std::string::String, - source_info: SourceInfo { - span: $DIR/coroutine.rs:19:6: 19:9 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { + coroutine layout { + field _s0: String; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug arg => (((*_18) as variant#4).0: std::string::String); + coroutine debug arg => _s0; 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<'_>); diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir index b4fcd2051303e..1abfe986f6867 100644 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir @@ -1,29 +1,19 @@ // MIR for `main::{closure#1}` after StateTransform -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: std::string::String, - source_info: SourceInfo { - span: $DIR/coroutine.rs:26:6: 26:9 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { + coroutine layout { + field _s0: String; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug arg => (((*_18) as variant#4).0: std::string::String); + coroutine debug arg => _s0; 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<'_>); diff --git a/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 222c7144ef07d..e5667215d54fd 100644 --- a/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -1,28 +1,18 @@ // MIR for `main::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: HasDrop, - source_info: SourceInfo { - span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> { + coroutine layout { + field _s0: HasDrop; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug _x => _2; + coroutine debug _d => _s0; let mut _0: std::ops::CoroutineState<(), ()>; let _3: HasDrop; let mut _4: !; From 3b77583f46f3e1d5fb836d38c3b9a7e7a53ebaa3 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 17 May 2026 15:20:10 +0000 Subject: [PATCH 3/5] Simplify can_unwind. --- compiler/rustc_mir_transform/src/coroutine.rs | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4ae6e9a8885d1..b18c7db387401 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1173,40 +1173,8 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { } // Unwinds can only start at certain terminators. - for block in body.basic_blocks.iter() { - match block.terminator().kind { - // These never unwind. - TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => {} - - // Resume will *continue* unwinding, but if there's no other unwinding terminator it - // will never be reached. - TerminatorKind::UnwindResume => {} - - TerminatorKind::Yield { .. } => { - unreachable!("`can_unwind` called before coroutine transform") - } - - // These may unwind. - TerminatorKind::Drop { .. } - | TerminatorKind::Call { .. } - | TerminatorKind::InlineAsm { .. } - | TerminatorKind::Assert { .. } => return true, - - TerminatorKind::TailCall { .. } => { - unreachable!("tail calls can't be present in generators") - } - } - } - + body.basic_blocks.iter().any(|block| block.terminator().unwind().is_some()) // If we didn't find an unwinding terminator, the function cannot unwind. - false } // Poison the coroutine when it unwinds From 9e5c064fa4b2efddd6aee32e75d0e72c9e6979cb Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 17 May 2026 15:43:18 +0000 Subject: [PATCH 4/5] Put entry block at the end instead of shifting everything. --- compiler/rustc_mir_transform/src/coroutine.rs | 39 +- ...nc_await.a-{closure#0}.StateTransform.diff | 56 ++ ...await.a-{closure#0}.coroutine_resume.0.mir | 46 -- ...nc_await.b-{closure#0}.StateTransform.diff | 543 ++++++++++++++++++ ...await.b-{closure#0}.coroutine_resume.0.mir | 405 ------------- tests/mir-opt/coroutine/async_await.rs | 4 +- ....main-{closure#0}.StateTransform.after.mir | 264 --------- ...utine.main-{closure#0}.StateTransform.diff | 353 ++++++++++++ ....main-{closure#1}.StateTransform.after.mir | 264 --------- ...utine.main-{closure#1}.StateTransform.diff | 353 ++++++++++++ tests/mir-opt/coroutine/coroutine.rs | 4 +- ...e#0}.StateTransform.before.panic-abort.mir | 83 --- ...#0}.StateTransform.before.panic-unwind.mir | 118 ---- ...closure#0}.StateTransform.panic-abort.diff | 141 +++++ ...losure#0}.StateTransform.panic-unwind.diff | 201 +++++++ .../coroutine_storage_dead_unwind.rs | 2 +- ..._tiny.main-{closure#0}.StateTransform.diff | 98 ++++ ...ny.main-{closure#0}.coroutine_resume.0.mir | 79 --- tests/mir-opt/coroutine/coroutine_tiny.rs | 6 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 158 ++--- ....run2-{closure#0}.Inline.panic-unwind.diff | 168 +++--- tests/ui/force-inlining/deny-async.stderr | 16 +- .../async-closure.stdout | 28 +- 23 files changed, 1964 insertions(+), 1465 deletions(-) create mode 100644 tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff delete mode 100644 tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir create mode 100644 tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff delete mode 100644 tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir delete mode 100644 tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir create mode 100644 tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff delete mode 100644 tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir create mode 100644 tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff delete mode 100644 tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir delete mode 100644 tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir create mode 100644 tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff create mode 100644 tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff create mode 100644 tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.StateTransform.diff delete mode 100644 tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index b18c7db387401..a00fad4bd599a 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1077,7 +1077,7 @@ fn compute_layout<'tcx>( /// Replaces the entry point of `body` with a block that switches on the coroutine discriminant and /// dispatches to blocks according to `cases`. /// -/// After this function, the former entry point of the function will be bb1. +/// After this function, the former entry point of the function will be the last block. fn insert_switch<'tcx>( body: &mut Body<'tcx>, cases: Vec<(usize, BasicBlock)>, @@ -1085,23 +1085,34 @@ fn insert_switch<'tcx>( default_block: BasicBlock, ) { let (assign, discr) = transform.get_discr(body); - let switch_targets = - SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block); - let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets }; - let source_info = SourceInfo::outermost(body.span); - body.basic_blocks_mut().raw.insert( - 0, - BasicBlockData::new_stmts( - vec![assign], - Some(Terminator { source_info, kind: switch }), - false, - ), + // MIR validation ensures that no block targets `ENTRY_BLOCK`. + #[cfg(debug_assertions)] + for bb in body.basic_blocks.iter() { + for target in bb.terminator().successors() { + assert_ne!(target, START_BLOCK); + } + } + + // Add the switch as entry block, and put the former entry block at the end. + let former_entry = std::mem::replace( + &mut body.basic_blocks_mut()[START_BLOCK], + BasicBlockData::new_stmts(vec![assign], None, false), ); + let former_entry = body.basic_blocks_mut().push(former_entry); - for b in body.basic_blocks_mut().iter_mut() { - b.terminator_mut().successors_mut(|target| *target += 1); + // We may point to `START_BLOCK` in our `cases`, replace it with `former_entry`. + let mut switch_targets = + SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block); + for bb in switch_targets.all_targets_mut() { + if *bb == START_BLOCK { + *bb = former_entry; + } } + + let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets }; + body.basic_blocks_mut()[START_BLOCK].terminator = + Some(Terminator { source_info: SourceInfo::outermost(body.span), kind: switch }); } fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { diff --git a/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff new file mode 100644 index 0000000000000..dddd66e73fd51 --- /dev/null +++ b/tests/mir-opt/coroutine/async_await.a-{closure#0}.StateTransform.diff @@ -0,0 +1,56 @@ +- // MIR for `a::{closure#0}` before StateTransform ++ // MIR for `a::{closure#0}` after StateTransform + +- fn a::{closure#0}(_1: {async fn body of a()}, _2: std::future::ResumeTy) -> () +- yields () +- { ++ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { ++ coroutine layout { ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ } ++ storage_conflicts = BitMatrix(0x0) {} ++ } + debug _task_context => _2; +- let mut _0: (); ++ let mut _0: std::task::Poll<()>; ++ let mut _3: (); ++ let mut _4: u32; ++ let mut _5: &mut {async fn body of a()}; + + bb0: { +- _0 = const (); +- drop(_1) -> [return: bb1, unwind: bb2]; ++ _5 = copy (_1.0: &mut {async fn body of a()}); ++ _4 = discriminant((*_5)); ++ switchInt(move _4) -> [0: bb5, 1: bb3, otherwise: bb4]; + } + + bb1: { ++ _0 = Poll::<()>::Ready(move _3); ++ discriminant((*_5)) = 1; + return; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ goto -> bb1; ++ } ++ ++ bb3: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb3, unwind continue]; ++ } ++ ++ bb4: { ++ unreachable; ++ } ++ ++ bb5: { ++ _3 = const (); ++ goto -> bb2; + } + } + diff --git a/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir deleted file mode 100644 index 539316c9725e4..0000000000000 --- a/tests/mir-opt/coroutine/async_await.a-{closure#0}.coroutine_resume.0.mir +++ /dev/null @@ -1,46 +0,0 @@ -// MIR for `a::{closure#0}` 0 coroutine_resume - -fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { - coroutine layout { - variant_fields = { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - } - storage_conflicts = BitMatrix(0x0) {} - } - debug _task_context => _2; - let mut _0: std::task::Poll<()>; - let mut _3: (); - let mut _4: u32; - let mut _5: &mut {async fn body of a()}; - - bb0: { - _5 = copy (_1.0: &mut {async fn body of a()}); - _4 = discriminant((*_5)); - switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5]; - } - - bb1: { - _3 = const (); - goto -> bb3; - } - - bb2: { - _0 = Poll::<()>::Ready(move _3); - discriminant((*_5)) = 1; - return; - } - - bb3: { - goto -> bb2; - } - - bb4: { - assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; - } - - bb5: { - unreachable; - } -} diff --git a/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff new file mode 100644 index 0000000000000..fdbc67d51bd34 --- /dev/null +++ b/tests/mir-opt/coroutine/async_await.b-{closure#0}.StateTransform.diff @@ -0,0 +1,543 @@ +- // MIR for `b::{closure#0}` before StateTransform ++ // MIR for `b::{closure#0}` after StateTransform + +- fn b::{closure#0}(_1: {async fn body of b()}, _2: std::future::ResumeTy) -> () +- yields () +- { ++ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { ++ coroutine layout { ++ field _s0: {async fn body of a()}; ++ field _s1: {async fn body of a()}; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0], ++ Suspend1 (4): [_s1], ++ } ++ storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)} ++ } + debug _task_context => _2; +- let mut _0: (); ++ coroutine debug __awaitee => _s0; ++ coroutine debug __awaitee => _s1; ++ let mut _0: std::task::Poll<()>; + let _3: (); + let mut _4: {async fn body of a()}; + let mut _5: {async fn body of a()}; + let mut _6: {async fn body of a()}; + let mut _7: (); + let _8: (); + let mut _9: std::task::Poll<()>; + let mut _10: std::pin::Pin<&mut {async fn body of a()}>; + let mut _11: &mut {async fn body of a()}; + let mut _12: &mut {async fn body of a()}; + let mut _13: &mut std::task::Context<'_>; + let mut _14: &mut std::task::Context<'_>; +- let mut _15: std::future::ResumeTy; ++ let mut _15: &mut std::task::Context<'_>; + let mut _16: isize; + let mut _18: !; +- let mut _19: std::future::ResumeTy; ++ let mut _19: &mut std::task::Context<'_>; + let mut _20: (); + let mut _21: {async fn body of a()}; + let mut _22: {async fn body of a()}; + let mut _23: {async fn body of a()}; + let _24: (); + let mut _25: std::task::Poll<()>; + let mut _26: std::pin::Pin<&mut {async fn body of a()}>; + let mut _27: &mut {async fn body of a()}; + let mut _28: &mut {async fn body of a()}; + let mut _29: &mut std::task::Context<'_>; + let mut _30: &mut std::task::Context<'_>; +- let mut _31: std::future::ResumeTy; ++ let mut _31: &mut std::task::Context<'_>; + let mut _32: isize; + let mut _34: !; +- let mut _35: std::future::ResumeTy; ++ let mut _35: &mut std::task::Context<'_>; + let mut _36: (); ++ let mut _37: (); ++ let mut _38: u32; ++ let mut _39: &mut {async fn body of b()}; + scope 1 { +- debug __awaitee => _6; ++ debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()}); + let _17: (); + scope 2 { + debug result => _17; + } + } + scope 3 { +- debug __awaitee => _23; ++ debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()}); + let _33: (); + scope 4 { + debug result => _33; + } + } + + bb0: { +- StorageLive(_3); +- StorageLive(_4); +- StorageLive(_5); +- _5 = a() -> [return: bb1, unwind: bb47]; ++ _39 = copy (_1.0: &mut {async fn body of b()}); ++ _38 = discriminant((*_39)); ++ switchInt(move _38) -> [0: bb47, 1: bb46, 2: bb45, 3: bb43, 4: bb44, otherwise: bb7]; + } + + bb1: { +- _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb2, unwind: bb46]; ++ _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb2, unwind: bb36]; + } + + bb2: { + StorageDead(_5); + PlaceMention(_4); +- StorageLive(_6); +- _6 = move _4; ++ nop; ++ (((*_39) as variant#3).0: {async fn body of a()}) = move _4; + goto -> bb3; + } + + bb3: { + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); +- _12 = &mut _6; ++ _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: bb4, unwind: bb43]; ++ _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb4, unwind: bb33]; + } + + bb4: { + StorageDead(_11); + StorageLive(_13); + StorageLive(_14); + StorageLive(_15); + _15 = copy _2; +- _14 = std::future::get_context::<'_, '_>(move _15) -> [return: bb5, unwind: bb41]; ++ _14 = move _15; ++ goto -> bb5; + } + + bb5: { + _13 = &mut (*_14); + StorageDead(_15); +- _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb6, unwind: bb42]; ++ _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb6, unwind: bb32]; + } + + bb6: { + StorageDead(_13); + StorageDead(_10); + PlaceMention(_9); + _16 = discriminant(_9); + switchInt(move _16) -> [0: bb9, 1: bb8, otherwise: bb7]; + } + + bb7: { + unreachable; + } + + bb8: { + _8 = const (); + StorageDead(_14); + StorageDead(_12); + StorageDead(_9); + StorageDead(_8); + StorageLive(_19); + StorageLive(_20); + _20 = (); +- _19 = yield(move _20) -> [resume: bb10, drop: bb28]; ++ _0 = Poll::<()>::Pending; ++ StorageDead(_3); ++ StorageDead(_4); ++ StorageDead(_19); ++ StorageDead(_20); ++ discriminant((*_39)) = 3; ++ return; + } + + bb9: { + StorageLive(_17); + _17 = copy ((_9 as Ready).0: ()); + _3 = copy _17; + StorageDead(_17); + StorageDead(_14); + StorageDead(_12); + StorageDead(_9); + StorageDead(_8); +- drop(_6) -> [return: bb11, unwind: bb45]; ++ drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb11, unwind: bb35]; + } + + bb10: { + StorageDead(_20); + _2 = move _19; + StorageDead(_19); + _7 = const (); + goto -> bb3; + } + + bb11: { +- StorageDead(_6); ++ nop; + goto -> bb12; + } + + bb12: { + StorageDead(_4); + StorageDead(_3); + StorageLive(_21); + StorageLive(_22); +- _22 = a() -> [return: bb13, unwind: bb39]; ++ _22 = a() -> [return: bb13, unwind: bb30]; + } + + bb13: { +- _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb14, unwind: bb38]; ++ _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb14, unwind: bb29]; + } + + bb14: { + StorageDead(_22); + PlaceMention(_21); +- StorageLive(_23); +- _23 = move _21; ++ nop; ++ (((*_39) as variant#4).0: {async fn body of a()}) = move _21; + goto -> bb15; + } + + bb15: { + StorageLive(_24); + StorageLive(_25); + StorageLive(_26); + StorageLive(_27); + StorageLive(_28); +- _28 = &mut _23; ++ _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: bb16, unwind: bb35]; ++ _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb16, unwind: bb26]; + } + + bb16: { + StorageDead(_27); + StorageLive(_29); + StorageLive(_30); + StorageLive(_31); + _31 = copy _2; +- _30 = std::future::get_context::<'_, '_>(move _31) -> [return: bb17, unwind: bb33]; ++ _30 = move _31; ++ goto -> bb17; + } + + bb17: { + _29 = &mut (*_30); + StorageDead(_31); +- _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb18, unwind: bb34]; ++ _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb18, unwind: bb25]; + } + + bb18: { + StorageDead(_29); + StorageDead(_26); + PlaceMention(_25); + _32 = discriminant(_25); + switchInt(move _32) -> [0: bb20, 1: bb19, otherwise: bb7]; + } + + bb19: { + _24 = const (); + StorageDead(_30); + StorageDead(_28); + StorageDead(_25); + StorageDead(_24); + StorageLive(_35); + StorageLive(_36); + _36 = (); +- _35 = yield(move _36) -> [resume: bb21, drop: bb25]; ++ _0 = Poll::<()>::Pending; ++ StorageDead(_21); ++ StorageDead(_35); ++ StorageDead(_36); ++ discriminant((*_39)) = 4; ++ return; + } + + bb20: { + StorageLive(_33); + _33 = copy ((_25 as Ready).0: ()); +- _0 = copy _33; ++ _37 = copy _33; + StorageDead(_33); + StorageDead(_30); + StorageDead(_28); + StorageDead(_25); + StorageDead(_24); +- drop(_23) -> [return: bb22, unwind: bb37]; ++ drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb22, unwind: bb28]; + } + + bb21: { + StorageDead(_36); + _2 = move _35; + StorageDead(_35); + _7 = const (); + goto -> bb15; + } + + bb22: { +- StorageDead(_23); ++ nop; + goto -> bb23; + } + + bb23: { + StorageDead(_21); +- drop(_1) -> [return: bb24, unwind: bb50]; ++ goto -> bb41; + } + + bb24: { ++ _0 = Poll::<()>::Ready(move _37); ++ discriminant((*_39)) = 1; + return; + } + +- bb25: { +- StorageDead(_36); +- StorageDead(_35); +- drop(_23) -> [return: bb26, unwind: bb51]; +- } +- +- bb26: { +- StorageDead(_23); +- goto -> bb27; +- } +- +- bb27: { +- StorageDead(_21); +- goto -> bb31; +- } +- +- bb28: { +- StorageDead(_20); +- StorageDead(_19); +- drop(_6) -> [return: bb29, unwind: bb53]; +- } +- +- bb29: { +- StorageDead(_6); +- goto -> bb30; +- } +- +- bb30: { +- StorageDead(_4); +- StorageDead(_3); +- goto -> bb31; +- } +- +- bb31: { +- drop(_1) -> [return: bb32, unwind: bb50]; +- } +- +- bb32: { +- coroutine_drop; +- } +- +- bb33 (cleanup): { +- StorageDead(_31); +- goto -> bb34; +- } +- +- bb34 (cleanup): { ++ bb25 (cleanup): { + StorageDead(_29); + StorageDead(_26); + StorageDead(_30); +- goto -> bb36; ++ goto -> bb27; + } + +- bb35 (cleanup): { ++ bb26 (cleanup): { + StorageDead(_27); + StorageDead(_26); +- goto -> bb36; ++ goto -> bb27; + } + +- bb36 (cleanup): { ++ bb27 (cleanup): { + StorageDead(_28); + StorageDead(_25); + StorageDead(_24); +- drop(_23) -> [return: bb37, unwind terminate(cleanup)]; ++ drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb28, unwind terminate(cleanup)]; + } + +- bb37 (cleanup): { +- StorageDead(_23); +- goto -> bb40; ++ bb28 (cleanup): { ++ nop; ++ goto -> bb31; + } + +- bb38 (cleanup): { +- goto -> bb39; ++ bb29 (cleanup): { ++ goto -> bb30; + } + +- bb39 (cleanup): { ++ bb30 (cleanup): { + StorageDead(_22); +- goto -> bb40; ++ goto -> bb31; + } + +- bb40 (cleanup): { ++ bb31 (cleanup): { + StorageDead(_21); +- goto -> bb49; ++ goto -> bb39; + } + +- bb41 (cleanup): { +- StorageDead(_15); +- goto -> bb42; +- } +- +- bb42 (cleanup): { ++ bb32 (cleanup): { + StorageDead(_13); + StorageDead(_10); + StorageDead(_14); +- goto -> bb44; ++ goto -> bb34; + } + +- bb43 (cleanup): { ++ bb33 (cleanup): { + StorageDead(_11); + StorageDead(_10); +- goto -> bb44; ++ goto -> bb34; + } + +- bb44 (cleanup): { ++ bb34 (cleanup): { + StorageDead(_12); + StorageDead(_9); + StorageDead(_8); +- drop(_6) -> [return: bb45, unwind terminate(cleanup)]; ++ drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb35, unwind terminate(cleanup)]; + } + +- bb45 (cleanup): { +- StorageDead(_6); +- goto -> bb48; ++ bb35 (cleanup): { ++ nop; ++ goto -> bb38; + } + +- bb46 (cleanup): { +- goto -> bb47; ++ bb36 (cleanup): { ++ goto -> bb37; + } + +- bb47 (cleanup): { ++ bb37 (cleanup): { + StorageDead(_5); +- goto -> bb48; ++ goto -> bb38; + } + +- bb48 (cleanup): { ++ bb38 (cleanup): { + StorageDead(_4); + StorageDead(_3); +- goto -> bb49; ++ goto -> bb39; + } + +- bb49 (cleanup): { +- drop(_1) -> [return: bb50, unwind terminate(cleanup)]; ++ bb39 (cleanup): { ++ goto -> bb40; + } + +- bb50 (cleanup): { ++ bb40 (cleanup): { ++ goto -> bb42; ++ } ++ ++ bb41: { ++ goto -> bb24; ++ } ++ ++ bb42 (cleanup): { ++ discriminant((*_39)) = 2; + resume; + } + +- bb51 (cleanup): { +- StorageDead(_23); +- goto -> bb52; ++ bb43: { ++ StorageLive(_3); ++ StorageLive(_4); ++ StorageLive(_19); ++ StorageLive(_20); ++ _19 = move _2; ++ goto -> bb10; + } + +- bb52 (cleanup): { +- StorageDead(_21); +- goto -> bb55; ++ bb44: { ++ StorageLive(_21); ++ StorageLive(_35); ++ StorageLive(_36); ++ _35 = move _2; ++ goto -> bb21; + } + +- bb53 (cleanup): { +- StorageDead(_6); +- goto -> bb54; ++ bb45: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb45, unwind continue]; + } + +- bb54 (cleanup): { +- StorageDead(_4); +- StorageDead(_3); +- goto -> bb55; ++ bb46: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb46, unwind continue]; + } + +- bb55 (cleanup): { +- drop(_1) -> [return: bb50, unwind terminate(cleanup)]; ++ bb47: { ++ StorageLive(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ _5 = a() -> [return: bb1, unwind: bb37]; + } + } + diff --git a/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir deleted file mode 100644 index 22e4a8cee6494..0000000000000 --- a/tests/mir-opt/coroutine/async_await.b-{closure#0}.coroutine_resume.0.mir +++ /dev/null @@ -1,405 +0,0 @@ -// MIR for `b::{closure#0}` 0 coroutine_resume - -fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { - coroutine layout { - field _s0: {async fn body of a()}; - field _s1: {async fn body of a()}; - variant_fields = { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s1], - } - storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)} - } - debug _task_context => _2; - coroutine debug __awaitee => _s0; - coroutine debug __awaitee => _s1; - let mut _0: std::task::Poll<()>; - let _3: (); - let mut _4: {async fn body of a()}; - let mut _5: {async fn body of a()}; - let mut _6: {async fn body of a()}; - let mut _7: (); - let _8: (); - let mut _9: std::task::Poll<()>; - let mut _10: std::pin::Pin<&mut {async fn body of a()}>; - let mut _11: &mut {async fn body of a()}; - let mut _12: &mut {async fn body of a()}; - let mut _13: &mut std::task::Context<'_>; - let mut _14: &mut std::task::Context<'_>; - let mut _15: &mut std::task::Context<'_>; - let mut _16: isize; - let mut _18: !; - let mut _19: &mut std::task::Context<'_>; - let mut _20: (); - let mut _21: {async fn body of a()}; - let mut _22: {async fn body of a()}; - let mut _23: {async fn body of a()}; - let _24: (); - let mut _25: std::task::Poll<()>; - let mut _26: std::pin::Pin<&mut {async fn body of a()}>; - let mut _27: &mut {async fn body of a()}; - let mut _28: &mut {async fn body of a()}; - let mut _29: &mut std::task::Context<'_>; - let mut _30: &mut std::task::Context<'_>; - let mut _31: &mut std::task::Context<'_>; - let mut _32: isize; - let mut _34: !; - let mut _35: &mut std::task::Context<'_>; - let mut _36: (); - let mut _37: (); - let mut _38: u32; - let mut _39: &mut {async fn body of b()}; - scope 1 { - debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()}); - let _17: (); - scope 2 { - debug result => _17; - } - } - scope 3 { - debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()}); - let _33: (); - scope 4 { - debug result => _33; - } - } - - bb0: { - _39 = copy (_1.0: &mut {async fn body of b()}); - _38 = discriminant((*_39)); - switchInt(move _38) -> [0: bb1, 1: bb47, 2: bb46, 3: bb44, 4: bb45, otherwise: bb8]; - } - - bb1: { - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - _5 = a() -> [return: bb2, unwind: bb38]; - } - - bb2: { - _4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind: bb37]; - } - - bb3: { - StorageDead(_5); - PlaceMention(_4); - nop; - (((*_39) as variant#3).0: {async fn body of a()}) = move _4; - goto -> bb4; - } - - bb4: { - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - StorageLive(_11); - StorageLive(_12); - _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: bb34]; - } - - bb5: { - StorageDead(_11); - StorageLive(_13); - StorageLive(_14); - StorageLive(_15); - _15 = copy _2; - _14 = move _15; - goto -> bb6; - } - - bb6: { - _13 = &mut (*_14); - StorageDead(_15); - _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind: bb33]; - } - - bb7: { - StorageDead(_13); - StorageDead(_10); - PlaceMention(_9); - _16 = discriminant(_9); - switchInt(move _16) -> [0: bb10, 1: bb9, otherwise: bb8]; - } - - bb8: { - unreachable; - } - - bb9: { - _8 = const (); - StorageDead(_14); - StorageDead(_12); - StorageDead(_9); - StorageDead(_8); - StorageLive(_19); - StorageLive(_20); - _20 = (); - _0 = Poll::<()>::Pending; - StorageDead(_3); - StorageDead(_4); - StorageDead(_19); - StorageDead(_20); - discriminant((*_39)) = 3; - return; - } - - bb10: { - StorageLive(_17); - _17 = copy ((_9 as Ready).0: ()); - _3 = copy _17; - StorageDead(_17); - StorageDead(_14); - StorageDead(_12); - StorageDead(_9); - StorageDead(_8); - drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind: bb36]; - } - - bb11: { - StorageDead(_20); - _2 = move _19; - StorageDead(_19); - _7 = const (); - goto -> bb4; - } - - bb12: { - nop; - goto -> bb13; - } - - bb13: { - StorageDead(_4); - StorageDead(_3); - StorageLive(_21); - StorageLive(_22); - _22 = a() -> [return: bb14, unwind: bb31]; - } - - bb14: { - _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind: bb30]; - } - - bb15: { - StorageDead(_22); - PlaceMention(_21); - nop; - (((*_39) as variant#4).0: {async fn body of a()}) = move _21; - goto -> bb16; - } - - bb16: { - StorageLive(_24); - StorageLive(_25); - StorageLive(_26); - StorageLive(_27); - 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: bb27]; - } - - bb17: { - StorageDead(_27); - StorageLive(_29); - StorageLive(_30); - StorageLive(_31); - _31 = copy _2; - _30 = move _31; - goto -> bb18; - } - - bb18: { - _29 = &mut (*_30); - StorageDead(_31); - _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind: bb26]; - } - - bb19: { - StorageDead(_29); - StorageDead(_26); - PlaceMention(_25); - _32 = discriminant(_25); - switchInt(move _32) -> [0: bb21, 1: bb20, otherwise: bb8]; - } - - bb20: { - _24 = const (); - StorageDead(_30); - StorageDead(_28); - StorageDead(_25); - StorageDead(_24); - StorageLive(_35); - StorageLive(_36); - _36 = (); - _0 = Poll::<()>::Pending; - StorageDead(_21); - StorageDead(_35); - StorageDead(_36); - discriminant((*_39)) = 4; - return; - } - - bb21: { - StorageLive(_33); - _33 = copy ((_25 as Ready).0: ()); - _37 = copy _33; - StorageDead(_33); - StorageDead(_30); - StorageDead(_28); - StorageDead(_25); - StorageDead(_24); - drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind: bb29]; - } - - bb22: { - StorageDead(_36); - _2 = move _35; - StorageDead(_35); - _7 = const (); - goto -> bb16; - } - - bb23: { - nop; - goto -> bb24; - } - - bb24: { - StorageDead(_21); - goto -> bb42; - } - - bb25: { - _0 = Poll::<()>::Ready(move _37); - discriminant((*_39)) = 1; - return; - } - - bb26 (cleanup): { - StorageDead(_29); - StorageDead(_26); - StorageDead(_30); - goto -> bb28; - } - - bb27 (cleanup): { - StorageDead(_27); - StorageDead(_26); - goto -> bb28; - } - - bb28 (cleanup): { - StorageDead(_28); - StorageDead(_25); - StorageDead(_24); - drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb29, unwind terminate(cleanup)]; - } - - bb29 (cleanup): { - nop; - goto -> bb32; - } - - bb30 (cleanup): { - goto -> bb31; - } - - bb31 (cleanup): { - StorageDead(_22); - goto -> bb32; - } - - bb32 (cleanup): { - StorageDead(_21); - goto -> bb40; - } - - bb33 (cleanup): { - StorageDead(_13); - StorageDead(_10); - StorageDead(_14); - goto -> bb35; - } - - bb34 (cleanup): { - StorageDead(_11); - StorageDead(_10); - goto -> bb35; - } - - bb35 (cleanup): { - StorageDead(_12); - StorageDead(_9); - StorageDead(_8); - drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb36, unwind terminate(cleanup)]; - } - - bb36 (cleanup): { - nop; - goto -> bb39; - } - - bb37 (cleanup): { - goto -> bb38; - } - - bb38 (cleanup): { - StorageDead(_5); - goto -> bb39; - } - - bb39 (cleanup): { - StorageDead(_4); - StorageDead(_3); - goto -> bb40; - } - - bb40 (cleanup): { - goto -> bb41; - } - - bb41 (cleanup): { - goto -> bb43; - } - - bb42: { - goto -> bb25; - } - - bb43 (cleanup): { - discriminant((*_39)) = 2; - resume; - } - - bb44: { - StorageLive(_3); - StorageLive(_4); - StorageLive(_19); - StorageLive(_20); - _19 = move _2; - goto -> bb11; - } - - bb45: { - StorageLive(_21); - StorageLive(_35); - StorageLive(_36); - _35 = move _2; - goto -> bb22; - } - - bb46: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb46, unwind continue]; - } - - bb47: { - assert(const false, "`async fn` resumed after completion") -> [success: bb47, unwind continue]; - } -} diff --git a/tests/mir-opt/coroutine/async_await.rs b/tests/mir-opt/coroutine/async_await.rs index 8334baa594720..4e506edb61cf5 100644 --- a/tests/mir-opt/coroutine/async_await.rs +++ b/tests/mir-opt/coroutine/async_await.rs @@ -8,7 +8,7 @@ #![crate_type = "lib"] -// EMIT_MIR async_await.a-{closure#0}.coroutine_resume.0.mir +// EMIT_MIR async_await.a-{closure#0}.StateTransform.diff async fn a() { // CHECK-LABEL: fn a::{closure#0}( // CHECK-SAME: _1: Pin<&mut {async fn body of a()}> @@ -17,7 +17,7 @@ async fn a() { // CHECK-NOT: get_context } -// EMIT_MIR async_await.b-{closure#0}.coroutine_resume.0.mir +// EMIT_MIR async_await.b-{closure#0}.StateTransform.diff pub async fn b() { // CHECK-LABEL: fn b::{closure#0}( // CHECK-SAME: _1: Pin<&mut {async fn body of b()}> diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir deleted file mode 100644 index 60e52d51829fc..0000000000000 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.after.mir +++ /dev/null @@ -1,264 +0,0 @@ -// MIR for `main::{closure#0}` after StateTransform - -fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { - coroutine layout { - field _s0: String; - variant_fields = { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - } - storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} - } - debug arg => (((*_18) as variant#4).0: std::string::String); - coroutine debug arg => _s0; - 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<'_>); - let mut _5: std::string::String; - let mut _6: &std::string::String; - let mut _7: &std::panic::Location<'_>; - let _8: std::string::String; - let mut _9: (&str, std::string::String, &std::panic::Location<'_>); - let mut _10: &str; - let _11: &str; - let mut _12: std::string::String; - let mut _13: &std::string::String; - let mut _14: &std::panic::Location<'_>; - let _15: &std::panic::Location<'_>; - let mut _16: (); - let mut _17: u32; - let mut _18: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}; - - bb0: { - _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}); - _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb35, 2: bb34, 3: bb32, 4: bb33, otherwise: bb36]; - } - - bb1: { - (((*_18) as variant#4).0: std::string::String) = move _2; - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - StorageLive(_6); - _6 = &(((*_18) as variant#4).0: std::string::String); - _5 = ::clone(move _6) -> [return: bb2, unwind: bb23]; - } - - bb2: { - StorageDead(_6); - StorageLive(_7); - _7 = Location::<'_>::caller() -> [return: bb3, unwind: bb22]; - } - - 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); - StorageDead(_4); - discriminant((*_18)) = 3; - return; - } - - bb5: { - goto -> bb6; - } - - bb6: { - StorageDead(_4); - drop(_3) -> [return: bb7, unwind: bb26]; - } - - bb7: { - StorageDead(_3); - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - StorageLive(_11); - _11 = const "second"; - _10 = &(*_11); - StorageLive(_12); - StorageLive(_13); - _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb8, unwind: bb20]; - } - - bb8: { - StorageDead(_13); - StorageLive(_14); - StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind: bb16]; - } - - bb9: { - _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); - StorageDead(_8); - StorageDead(_9); - StorageDead(_11); - StorageDead(_15); - discriminant((*_18)) = 4; - return; - } - - bb11: { - goto -> bb12; - } - - bb12: { - StorageDead(_9); - drop(_8) -> [return: bb13, unwind: bb19]; - } - - bb13: { - StorageDead(_15); - StorageDead(_11); - StorageDead(_8); - _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind: bb28]; - } - - bb14: { - goto -> bb30; - } - - bb15: { - _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); - discriminant((*_18)) = 1; - return; - } - - bb16 (cleanup): { - StorageDead(_14); - drop(_12) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { - StorageDead(_12); - StorageDead(_10); - goto -> bb18; - } - - bb18 (cleanup): { - StorageDead(_9); - goto -> bb19; - } - - bb19 (cleanup): { - StorageDead(_15); - goto -> bb21; - } - - bb20 (cleanup): { - StorageDead(_13); - StorageDead(_12); - StorageDead(_10); - StorageDead(_9); - goto -> bb21; - } - - bb21 (cleanup): { - StorageDead(_11); - StorageDead(_8); - goto -> bb27; - } - - bb22 (cleanup): { - StorageDead(_7); - drop(_5) -> [return: bb24, unwind terminate(cleanup)]; - } - - bb23 (cleanup): { - StorageDead(_6); - goto -> bb24; - } - - bb24 (cleanup): { - StorageDead(_5); - goto -> bb25; - } - - bb25 (cleanup): { - StorageDead(_4); - goto -> bb26; - } - - bb26 (cleanup): { - StorageDead(_3); - goto -> bb27; - } - - bb27 (cleanup): { - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb28, unwind terminate(cleanup)]; - } - - bb28 (cleanup): { - goto -> bb29; - } - - bb29 (cleanup): { - goto -> bb31; - } - - bb30: { - goto -> bb15; - } - - bb31 (cleanup): { - discriminant((*_18)) = 2; - resume; - } - - bb32: { - StorageLive(_3); - StorageLive(_4); - _3 = move _2; - goto -> bb5; - } - - bb33: { - StorageLive(_8); - StorageLive(_9); - StorageLive(_11); - StorageLive(_15); - _8 = move _2; - goto -> bb11; - } - - bb34: { - assert(const false, "coroutine resumed after panicking") -> [success: bb34, unwind continue]; - } - - bb35: { - assert(const false, "coroutine resumed after completion") -> [success: bb35, unwind continue]; - } - - bb36: { - unreachable; - } -} - -ALLOC0 (size: 6, align: 1) { - 73 65 63 6f 6e 64 │ second -} - -ALLOC1 (size: 5, align: 1) { - 66 69 72 73 74 │ first -} diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff new file mode 100644 index 0000000000000..17671228295e3 --- /dev/null +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#0}.StateTransform.diff @@ -0,0 +1,353 @@ +- // MIR for `main::{closure#0}` before StateTransform ++ // MIR for `main::{closure#0}` after StateTransform + +- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine.rs:19:5: 19:18}, _2: String) -> () +- yields (&str, String, &Location<'_>) +- { +- debug arg => _2; +- let mut _0: (); ++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { ++ coroutine layout { ++ field _s0: String; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0], ++ Suspend1 (4): [_s0], ++ } ++ storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} ++ } ++ debug arg => (((*_18) as variant#4).0: std::string::String); ++ coroutine debug arg => _s0; ++ 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<'_>); + let mut _5: std::string::String; + let mut _6: &std::string::String; + let mut _7: &std::panic::Location<'_>; + let _8: std::string::String; + let mut _9: (&str, std::string::String, &std::panic::Location<'_>); + let mut _10: &str; + let _11: &str; + let mut _12: std::string::String; + let mut _13: &std::string::String; + let mut _14: &std::panic::Location<'_>; + let _15: &std::panic::Location<'_>; ++ let mut _16: (); ++ let mut _17: u32; ++ let mut _18: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}; + + bb0: { +- StorageLive(_3); +- StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = &_2; +- _5 = ::clone(move _6) -> [return: bb1, unwind: bb31]; ++ _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:19:5: 19:18}); ++ _17 = discriminant((*_18)); ++ switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35]; + } + + bb1: { + StorageDead(_6); + StorageLive(_7); +- _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb30]; ++ _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb21]; + } + + bb2: { + _4 = (const "first", move _5, move _7); + StorageDead(_7); + goto -> bb3; + } + + bb3: { + StorageDead(_5); +- _3 = yield(move _4) -> [resume: bb4, drop: bb18]; ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); ++ StorageDead(_3); ++ StorageDead(_4); ++ discriminant((*_18)) = 3; ++ return; + } + + bb4: { + goto -> bb5; + } + + bb5: { + StorageDead(_4); +- drop(_3) -> [return: bb6, unwind: bb34]; ++ drop(_3) -> [return: bb6, unwind: bb25]; + } + + bb6: { + StorageDead(_3); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = const "second"; + _10 = &(*_11); + StorageLive(_12); + StorageLive(_13); +- _13 = &_2; +- _12 = ::clone(move _13) -> [return: bb7, unwind: bb28]; ++ _13 = &(((*_18) as variant#4).0: std::string::String); ++ _12 = ::clone(move _13) -> [return: bb7, unwind: bb19]; + } + + bb7: { + StorageDead(_13); + StorageLive(_14); + StorageLive(_15); +- _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb24]; ++ _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb15]; + } + + bb8: { + _14 = &(*_15); + _9 = (move _10, move _12, move _14); + StorageDead(_14); + goto -> bb9; + } + + bb9: { + StorageDead(_12); + StorageDead(_10); +- _8 = yield(move _9) -> [resume: bb10, drop: bb15]; ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9); ++ StorageDead(_8); ++ StorageDead(_9); ++ StorageDead(_11); ++ StorageDead(_15); ++ discriminant((*_18)) = 4; ++ return; + } + + bb10: { + goto -> bb11; + } + + bb11: { + StorageDead(_9); +- drop(_8) -> [return: bb12, unwind: bb27]; ++ drop(_8) -> [return: bb12, unwind: bb18]; + } + + bb12: { + StorageDead(_15); + StorageDead(_11); + StorageDead(_8); +- _0 = const (); +- drop(_2) -> [return: bb13, unwind: bb36]; ++ _16 = const (); ++ drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb13, unwind: bb27]; + } + + bb13: { +- drop(_1) -> [return: bb14, unwind: bb37]; ++ goto -> bb29; + } + + bb14: { ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); ++ discriminant((*_18)) = 1; + return; + } + +- bb15: { +- goto -> bb16; ++ bb15 (cleanup): { ++ StorageDead(_14); ++ drop(_12) -> [return: bb16, unwind terminate(cleanup)]; + } + +- bb16: { +- StorageDead(_9); ++ bb16 (cleanup): { ++ StorageDead(_12); ++ StorageDead(_10); + goto -> bb17; + } + +- bb17: { +- StorageDead(_15); +- StorageDead(_11); +- StorageDead(_8); +- goto -> bb21; ++ bb17 (cleanup): { ++ StorageDead(_9); ++ goto -> bb18; + } + +- bb18: { +- goto -> bb19; ++ bb18 (cleanup): { ++ StorageDead(_15); ++ goto -> bb20; + } + +- bb19: { +- StorageDead(_4); ++ bb19 (cleanup): { ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_10); ++ StorageDead(_9); + goto -> bb20; + } + +- bb20: { +- StorageDead(_3); +- goto -> bb21; ++ bb20 (cleanup): { ++ StorageDead(_11); ++ StorageDead(_8); ++ goto -> bb26; + } + +- bb21: { +- drop(_2) -> [return: bb22, unwind: bb38]; ++ bb21 (cleanup): { ++ StorageDead(_7); ++ drop(_5) -> [return: bb23, unwind terminate(cleanup)]; + } + +- bb22: { +- drop(_1) -> [return: bb23, unwind: bb37]; ++ bb22 (cleanup): { ++ StorageDead(_6); ++ goto -> bb23; + } + +- bb23: { +- coroutine_drop; ++ bb23 (cleanup): { ++ StorageDead(_5); ++ goto -> bb24; + } + + bb24 (cleanup): { +- StorageDead(_14); +- drop(_12) -> [return: bb25, unwind terminate(cleanup)]; ++ StorageDead(_4); ++ goto -> bb25; + } + + bb25 (cleanup): { +- StorageDead(_12); +- StorageDead(_10); ++ StorageDead(_3); + goto -> bb26; + } + + bb26 (cleanup): { +- StorageDead(_9); +- goto -> bb27; ++ drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb27, unwind terminate(cleanup)]; + } + + bb27 (cleanup): { +- StorageDead(_15); +- goto -> bb29; ++ goto -> bb28; + } + + bb28 (cleanup): { +- StorageDead(_13); +- StorageDead(_12); +- StorageDead(_10); +- StorageDead(_9); +- goto -> bb29; ++ goto -> bb30; + } + +- bb29 (cleanup): { +- StorageDead(_11); +- StorageDead(_8); +- goto -> bb35; ++ bb29: { ++ goto -> bb14; + } + + bb30 (cleanup): { +- StorageDead(_7); +- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; ++ discriminant((*_18)) = 2; ++ resume; + } + +- bb31 (cleanup): { +- StorageDead(_6); +- goto -> bb32; ++ bb31: { ++ StorageLive(_3); ++ StorageLive(_4); ++ _3 = move _2; ++ goto -> bb4; + } + +- bb32 (cleanup): { +- StorageDead(_5); +- goto -> bb33; ++ bb32: { ++ StorageLive(_8); ++ StorageLive(_9); ++ StorageLive(_11); ++ StorageLive(_15); ++ _8 = move _2; ++ goto -> bb10; + } + +- bb33 (cleanup): { +- StorageDead(_4); +- goto -> bb34; ++ bb33: { ++ assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue]; + } + +- bb34 (cleanup): { +- StorageDead(_3); +- goto -> bb35; ++ bb34: { ++ assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue]; + } + +- bb35 (cleanup): { +- drop(_2) -> [return: bb36, unwind terminate(cleanup)]; ++ bb35: { ++ unreachable; + } + +- bb36 (cleanup): { +- drop(_1) -> [return: bb37, unwind terminate(cleanup)]; +- } +- +- bb37 (cleanup): { +- resume; +- } +- +- bb38 (cleanup): { +- drop(_1) -> [return: bb37, unwind terminate(cleanup)]; ++ bb36: { ++ (((*_18) as variant#4).0: std::string::String) = move _2; ++ StorageLive(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ _6 = &(((*_18) as variant#4).0: std::string::String); ++ _5 = ::clone(move _6) -> [return: bb1, unwind: bb22]; + } + } + + ALLOC0 (size: 6, align: 1) { + 73 65 63 6f 6e 64 │ second + } + + ALLOC1 (size: 5, align: 1) { + 66 69 72 73 74 │ first + } + diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir deleted file mode 100644 index 1abfe986f6867..0000000000000 --- a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.after.mir +++ /dev/null @@ -1,264 +0,0 @@ -// MIR for `main::{closure#1}` after StateTransform - -fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { - coroutine layout { - field _s0: String; - variant_fields = { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - } - storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} - } - debug arg => (((*_18) as variant#4).0: std::string::String); - coroutine debug arg => _s0; - 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<'_>); - let mut _5: std::string::String; - let mut _6: &std::string::String; - let mut _7: &std::panic::Location<'_>; - let _8: std::string::String; - let mut _9: (&str, std::string::String, &std::panic::Location<'_>); - let mut _10: &str; - let _11: &str; - let mut _12: std::string::String; - let mut _13: &std::string::String; - let mut _14: &std::panic::Location<'_>; - let _15: &std::panic::Location<'_>; - let mut _16: (); - let mut _17: u32; - let mut _18: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}; - - bb0: { - _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}); - _17 = discriminant((*_18)); - switchInt(move _17) -> [0: bb1, 1: bb35, 2: bb34, 3: bb32, 4: bb33, otherwise: bb36]; - } - - bb1: { - (((*_18) as variant#4).0: std::string::String) = move _2; - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - StorageLive(_6); - _6 = &(((*_18) as variant#4).0: std::string::String); - _5 = ::clone(move _6) -> [return: bb2, unwind: bb23]; - } - - bb2: { - StorageDead(_6); - StorageLive(_7); - _7 = Location::<'_>::caller() -> [return: bb3, unwind: bb22]; - } - - 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); - StorageDead(_4); - discriminant((*_18)) = 3; - return; - } - - bb5: { - goto -> bb6; - } - - bb6: { - StorageDead(_4); - drop(_3) -> [return: bb7, unwind: bb26]; - } - - bb7: { - StorageDead(_3); - StorageLive(_8); - StorageLive(_9); - StorageLive(_10); - StorageLive(_11); - _11 = const "second"; - _10 = &(*_11); - StorageLive(_12); - StorageLive(_13); - _13 = &(((*_18) as variant#4).0: std::string::String); - _12 = ::clone(move _13) -> [return: bb8, unwind: bb20]; - } - - bb8: { - StorageDead(_13); - StorageLive(_14); - StorageLive(_15); - _15 = Location::<'_>::caller() -> [return: bb9, unwind: bb16]; - } - - bb9: { - _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); - StorageDead(_8); - StorageDead(_9); - StorageDead(_11); - StorageDead(_15); - discriminant((*_18)) = 4; - return; - } - - bb11: { - goto -> bb12; - } - - bb12: { - StorageDead(_9); - drop(_8) -> [return: bb13, unwind: bb19]; - } - - bb13: { - StorageDead(_15); - StorageDead(_11); - StorageDead(_8); - _16 = const (); - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb14, unwind: bb28]; - } - - bb14: { - goto -> bb30; - } - - bb15: { - _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); - discriminant((*_18)) = 1; - return; - } - - bb16 (cleanup): { - StorageDead(_14); - drop(_12) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { - StorageDead(_12); - StorageDead(_10); - goto -> bb18; - } - - bb18 (cleanup): { - StorageDead(_9); - goto -> bb19; - } - - bb19 (cleanup): { - StorageDead(_15); - goto -> bb21; - } - - bb20 (cleanup): { - StorageDead(_13); - StorageDead(_12); - StorageDead(_10); - StorageDead(_9); - goto -> bb21; - } - - bb21 (cleanup): { - StorageDead(_11); - StorageDead(_8); - goto -> bb27; - } - - bb22 (cleanup): { - StorageDead(_7); - drop(_5) -> [return: bb24, unwind terminate(cleanup)]; - } - - bb23 (cleanup): { - StorageDead(_6); - goto -> bb24; - } - - bb24 (cleanup): { - StorageDead(_5); - goto -> bb25; - } - - bb25 (cleanup): { - StorageDead(_4); - goto -> bb26; - } - - bb26 (cleanup): { - StorageDead(_3); - goto -> bb27; - } - - bb27 (cleanup): { - drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb28, unwind terminate(cleanup)]; - } - - bb28 (cleanup): { - goto -> bb29; - } - - bb29 (cleanup): { - goto -> bb31; - } - - bb30: { - goto -> bb15; - } - - bb31 (cleanup): { - discriminant((*_18)) = 2; - resume; - } - - bb32: { - StorageLive(_3); - StorageLive(_4); - _3 = move _2; - goto -> bb5; - } - - bb33: { - StorageLive(_8); - StorageLive(_9); - StorageLive(_11); - StorageLive(_15); - _8 = move _2; - goto -> bb11; - } - - bb34: { - assert(const false, "coroutine resumed after panicking") -> [success: bb34, unwind continue]; - } - - bb35: { - assert(const false, "coroutine resumed after completion") -> [success: bb35, unwind continue]; - } - - bb36: { - unreachable; - } -} - -ALLOC0 (size: 6, align: 1) { - 73 65 63 6f 6e 64 │ second -} - -ALLOC1 (size: 5, align: 1) { - 66 69 72 73 74 │ first -} diff --git a/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff new file mode 100644 index 0000000000000..97c45da8a18f1 --- /dev/null +++ b/tests/mir-opt/coroutine/coroutine.main-{closure#1}.StateTransform.diff @@ -0,0 +1,353 @@ +- // MIR for `main::{closure#1}` before StateTransform ++ // MIR for `main::{closure#1}` after StateTransform + +- fn main::{closure#1}(_1: {coroutine@$DIR/coroutine.rs:26:5: 26:18}, _2: String) -> () +- yields (&str, String, &Location<'_>) +- { +- debug arg => _2; +- let mut _0: (); ++ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { ++ coroutine layout { ++ field _s0: String; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0], ++ Suspend1 (4): [_s0], ++ } ++ storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} ++ } ++ debug arg => (((*_18) as variant#4).0: std::string::String); ++ coroutine debug arg => _s0; ++ 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<'_>); + let mut _5: std::string::String; + let mut _6: &std::string::String; + let mut _7: &std::panic::Location<'_>; + let _8: std::string::String; + let mut _9: (&str, std::string::String, &std::panic::Location<'_>); + let mut _10: &str; + let _11: &str; + let mut _12: std::string::String; + let mut _13: &std::string::String; + let mut _14: &std::panic::Location<'_>; + let _15: &std::panic::Location<'_>; ++ let mut _16: (); ++ let mut _17: u32; ++ let mut _18: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}; + + bb0: { +- StorageLive(_3); +- StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = &_2; +- _5 = ::clone(move _6) -> [return: bb1, unwind: bb31]; ++ _18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:26:5: 26:18}); ++ _17 = discriminant((*_18)); ++ switchInt(move _17) -> [0: bb36, 1: bb34, 2: bb33, 3: bb31, 4: bb32, otherwise: bb35]; + } + + bb1: { + StorageDead(_6); + StorageLive(_7); +- _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb30]; ++ _7 = Location::<'_>::caller() -> [return: bb2, unwind: bb21]; + } + + bb2: { + _4 = (const "first", move _5, move _7); + StorageDead(_7); + goto -> bb3; + } + + bb3: { + StorageDead(_5); +- _3 = yield(move _4) -> [resume: bb4, drop: bb18]; ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4); ++ StorageDead(_3); ++ StorageDead(_4); ++ discriminant((*_18)) = 3; ++ return; + } + + bb4: { + goto -> bb5; + } + + bb5: { + StorageDead(_4); +- drop(_3) -> [return: bb6, unwind: bb34]; ++ drop(_3) -> [return: bb6, unwind: bb25]; + } + + bb6: { + StorageDead(_3); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = const "second"; + _10 = &(*_11); + StorageLive(_12); + StorageLive(_13); +- _13 = &_2; +- _12 = ::clone(move _13) -> [return: bb7, unwind: bb28]; ++ _13 = &(((*_18) as variant#4).0: std::string::String); ++ _12 = ::clone(move _13) -> [return: bb7, unwind: bb19]; + } + + bb7: { + StorageDead(_13); + StorageLive(_14); + StorageLive(_15); +- _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb24]; ++ _15 = Location::<'_>::caller() -> [return: bb8, unwind: bb15]; + } + + bb8: { + _14 = &(*_15); + _9 = (move _10, move _12, move _14); + StorageDead(_14); + goto -> bb9; + } + + bb9: { + StorageDead(_12); + StorageDead(_10); +- _8 = yield(move _9) -> [resume: bb10, drop: bb15]; ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _9); ++ StorageDead(_8); ++ StorageDead(_9); ++ StorageDead(_11); ++ StorageDead(_15); ++ discriminant((*_18)) = 4; ++ return; + } + + bb10: { + goto -> bb11; + } + + bb11: { + StorageDead(_9); +- drop(_8) -> [return: bb12, unwind: bb27]; ++ drop(_8) -> [return: bb12, unwind: bb18]; + } + + bb12: { + StorageDead(_15); + StorageDead(_11); + StorageDead(_8); +- _0 = const (); +- drop(_2) -> [return: bb13, unwind: bb36]; ++ _16 = const (); ++ drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb13, unwind: bb27]; + } + + bb13: { +- drop(_1) -> [return: bb14, unwind: bb37]; ++ goto -> bb29; + } + + bb14: { ++ _0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16); ++ discriminant((*_18)) = 1; + return; + } + +- bb15: { +- goto -> bb16; ++ bb15 (cleanup): { ++ StorageDead(_14); ++ drop(_12) -> [return: bb16, unwind terminate(cleanup)]; + } + +- bb16: { +- StorageDead(_9); ++ bb16 (cleanup): { ++ StorageDead(_12); ++ StorageDead(_10); + goto -> bb17; + } + +- bb17: { +- StorageDead(_15); +- StorageDead(_11); +- StorageDead(_8); +- goto -> bb21; ++ bb17 (cleanup): { ++ StorageDead(_9); ++ goto -> bb18; + } + +- bb18: { +- goto -> bb19; ++ bb18 (cleanup): { ++ StorageDead(_15); ++ goto -> bb20; + } + +- bb19: { +- StorageDead(_4); ++ bb19 (cleanup): { ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_10); ++ StorageDead(_9); + goto -> bb20; + } + +- bb20: { +- StorageDead(_3); +- goto -> bb21; ++ bb20 (cleanup): { ++ StorageDead(_11); ++ StorageDead(_8); ++ goto -> bb26; + } + +- bb21: { +- drop(_2) -> [return: bb22, unwind: bb38]; ++ bb21 (cleanup): { ++ StorageDead(_7); ++ drop(_5) -> [return: bb23, unwind terminate(cleanup)]; + } + +- bb22: { +- drop(_1) -> [return: bb23, unwind: bb37]; ++ bb22 (cleanup): { ++ StorageDead(_6); ++ goto -> bb23; + } + +- bb23: { +- coroutine_drop; ++ bb23 (cleanup): { ++ StorageDead(_5); ++ goto -> bb24; + } + + bb24 (cleanup): { +- StorageDead(_14); +- drop(_12) -> [return: bb25, unwind terminate(cleanup)]; ++ StorageDead(_4); ++ goto -> bb25; + } + + bb25 (cleanup): { +- StorageDead(_12); +- StorageDead(_10); ++ StorageDead(_3); + goto -> bb26; + } + + bb26 (cleanup): { +- StorageDead(_9); +- goto -> bb27; ++ drop((((*_18) as variant#4).0: std::string::String)) -> [return: bb27, unwind terminate(cleanup)]; + } + + bb27 (cleanup): { +- StorageDead(_15); +- goto -> bb29; ++ goto -> bb28; + } + + bb28 (cleanup): { +- StorageDead(_13); +- StorageDead(_12); +- StorageDead(_10); +- StorageDead(_9); +- goto -> bb29; ++ goto -> bb30; + } + +- bb29 (cleanup): { +- StorageDead(_11); +- StorageDead(_8); +- goto -> bb35; ++ bb29: { ++ goto -> bb14; + } + + bb30 (cleanup): { +- StorageDead(_7); +- drop(_5) -> [return: bb32, unwind terminate(cleanup)]; ++ discriminant((*_18)) = 2; ++ resume; + } + +- bb31 (cleanup): { +- StorageDead(_6); +- goto -> bb32; ++ bb31: { ++ StorageLive(_3); ++ StorageLive(_4); ++ _3 = move _2; ++ goto -> bb4; + } + +- bb32 (cleanup): { +- StorageDead(_5); +- goto -> bb33; ++ bb32: { ++ StorageLive(_8); ++ StorageLive(_9); ++ StorageLive(_11); ++ StorageLive(_15); ++ _8 = move _2; ++ goto -> bb10; + } + +- bb33 (cleanup): { +- StorageDead(_4); +- goto -> bb34; ++ bb33: { ++ assert(const false, "coroutine resumed after panicking") -> [success: bb33, unwind continue]; + } + +- bb34 (cleanup): { +- StorageDead(_3); +- goto -> bb35; ++ bb34: { ++ assert(const false, "coroutine resumed after completion") -> [success: bb34, unwind continue]; + } + +- bb35 (cleanup): { +- drop(_2) -> [return: bb36, unwind terminate(cleanup)]; ++ bb35: { ++ unreachable; + } + +- bb36 (cleanup): { +- drop(_1) -> [return: bb37, unwind terminate(cleanup)]; +- } +- +- bb37 (cleanup): { +- resume; +- } +- +- bb38 (cleanup): { +- drop(_1) -> [return: bb37, unwind terminate(cleanup)]; ++ bb36: { ++ (((*_18) as variant#4).0: std::string::String) = move _2; ++ StorageLive(_3); ++ StorageLive(_4); ++ StorageLive(_5); ++ StorageLive(_6); ++ _6 = &(((*_18) as variant#4).0: std::string::String); ++ _5 = ::clone(move _6) -> [return: bb1, unwind: bb22]; + } + } + + ALLOC0 (size: 6, align: 1) { + 73 65 63 6f 6e 64 │ second + } + + ALLOC1 (size: 5, align: 1) { + 66 69 72 73 74 │ first + } + diff --git a/tests/mir-opt/coroutine/coroutine.rs b/tests/mir-opt/coroutine/coroutine.rs index 41fdbee119e14..15d3cbb7c99f4 100644 --- a/tests/mir-opt/coroutine/coroutine.rs +++ b/tests/mir-opt/coroutine/coroutine.rs @@ -12,8 +12,8 @@ use std::ops::{Coroutine, CoroutineState}; use std::panic::Location; use std::pin::Pin; -// EMIT_MIR coroutine.main-{closure#0}.StateTransform.after.mir -// EMIT_MIR coroutine.main-{closure#1}.StateTransform.after.mir +// EMIT_MIR coroutine.main-{closure#0}.StateTransform.diff +// EMIT_MIR coroutine.main-{closure#1}.StateTransform.diff fn main() { let simple = #[coroutine] |arg: String| { diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir deleted file mode 100644 index 4731aed335d9f..0000000000000 --- a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir +++ /dev/null @@ -1,83 +0,0 @@ -// MIR for `main::{closure#0}` before StateTransform - -fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () -yields () - { - let mut _0: (); - let _3: Foo; - let _5: (); - let mut _6: (); - let _7: (); - let mut _8: Foo; - let _9: (); - let mut _10: Bar; - scope 1 { - debug a => _3; - let _4: Bar; - scope 2 { - debug b => _4; - } - } - - 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]; - } - - bb1: { - StorageDead(_6); - StorageDead(_5); - StorageLive(_7); - StorageLive(_8); - _8 = move _3; - _7 = take::(move _8) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_8); - StorageDead(_7); - StorageLive(_9); - StorageLive(_10); - _10 = move _4; - _9 = take::(move _10) -> [return: bb3, unwind unreachable]; - } - - bb3: { - StorageDead(_10); - StorageDead(_9); - _0 = const (); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_3); - drop(_1) -> [return: bb5, unwind unreachable]; - } - - bb5: { - return; - } - - bb6: { - StorageDead(_6); - StorageDead(_5); - StorageDead(_4); - drop(_3) -> [return: bb7, unwind unreachable]; - } - - bb7: { - StorageDead(_3); - drop(_1) -> [return: bb8, unwind unreachable]; - } - - bb8: { - coroutine_drop; - } -} diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir deleted file mode 100644 index 14e1782b86016..0000000000000 --- a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ /dev/null @@ -1,118 +0,0 @@ -// MIR for `main::{closure#0}` before StateTransform - -fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () -yields () - { - let mut _0: (); - let _3: Foo; - let _5: (); - let mut _6: (); - let _7: (); - let mut _8: Foo; - let _9: (); - let mut _10: Bar; - scope 1 { - debug a => _3; - let _4: Bar; - scope 2 { - debug b => _4; - } - } - - 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]; - } - - bb1: { - StorageDead(_6); - StorageDead(_5); - StorageLive(_7); - StorageLive(_8); - _8 = move _3; - _7 = take::(move _8) -> [return: bb2, unwind: bb10]; - } - - bb2: { - StorageDead(_8); - StorageDead(_7); - StorageLive(_9); - StorageLive(_10); - _10 = move _4; - _9 = take::(move _10) -> [return: bb3, unwind: bb9]; - } - - bb3: { - StorageDead(_10); - StorageDead(_9); - _0 = const (); - StorageDead(_4); - goto -> bb4; - } - - bb4: { - StorageDead(_3); - drop(_1) -> [return: bb5, unwind: bb14]; - } - - bb5: { - return; - } - - bb6: { - StorageDead(_6); - StorageDead(_5); - StorageDead(_4); - drop(_3) -> [return: bb7, unwind: bb15]; - } - - bb7: { - StorageDead(_3); - drop(_1) -> [return: bb8, unwind: bb14]; - } - - bb8: { - coroutine_drop; - } - - bb9 (cleanup): { - StorageDead(_10); - StorageDead(_9); - goto -> bb12; - } - - bb10 (cleanup): { - goto -> bb11; - } - - bb11 (cleanup): { - StorageDead(_8); - StorageDead(_7); - goto -> bb12; - } - - bb12 (cleanup): { - StorageDead(_4); - goto -> bb13; - } - - bb13 (cleanup): { - StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; - } - - bb14 (cleanup): { - resume; - } - - bb15 (cleanup): { - StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate(cleanup)]; - } -} diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff new file mode 100644 index 0000000000000..9e4fb0cb64788 --- /dev/null +++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-abort.diff @@ -0,0 +1,141 @@ +- // MIR for `main::{closure#0}` before StateTransform ++ // MIR for `main::{closure#0}` after StateTransform + +- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () +- yields () +- { +- let mut _0: (); ++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}>, _2: ()) -> CoroutineState<(), ()> { ++ coroutine layout { ++ field _s0: Foo; ++ field _s1: Bar; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0, _s1], ++ } ++ storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s0, _s1), (_s1, _s0), (_s1, _s1)} ++ } ++ coroutine debug a => _s0; ++ let mut _0: std::ops::CoroutineState<(), ()>; + let _3: Foo; + let _5: (); + let mut _6: (); + let _7: (); + let mut _8: Foo; + let _9: (); + let mut _10: Bar; ++ let mut _11: (); ++ let mut _12: u32; ++ let mut _13: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}; + scope 1 { +- debug a => _3; ++ debug a => (((*_13) as variant#3).0: Foo); ++ coroutine debug b => _s1; + let _4: Bar; + scope 2 { +- debug b => _4; ++ debug b => (((*_13) as variant#3).1: Bar); + } + } + + 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]; ++ _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}); ++ _12 = discriminant((*_13)); ++ switchInt(move _12) -> [0: bb10, 1: bb8, 3: bb7, otherwise: bb9]; + } + + bb1: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_7); + StorageLive(_8); +- _8 = move _3; ++ _8 = move (((*_13) as variant#3).0: Foo); + _7 = take::(move _8) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_9); + StorageLive(_10); +- _10 = move _4; ++ _10 = move (((*_13) as variant#3).1: Bar); + _9 = take::(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); +- _0 = const (); +- StorageDead(_4); ++ _11 = const (); ++ nop; + goto -> bb4; + } + + bb4: { +- StorageDead(_3); +- drop(_1) -> [return: bb5, unwind unreachable]; ++ nop; ++ goto -> bb6; + } + + bb5: { ++ _0 = CoroutineState::<(), ()>::Complete(move _11); ++ discriminant((*_13)) = 1; + return; + } + + bb6: { +- StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); +- drop(_3) -> [return: bb7, unwind unreachable]; ++ goto -> bb5; + } + + bb7: { +- StorageDead(_3); +- drop(_1) -> [return: bb8, unwind unreachable]; ++ StorageLive(_5); ++ StorageLive(_6); ++ _5 = move _2; ++ goto -> bb1; + } + + bb8: { +- coroutine_drop; ++ assert(const false, "coroutine resumed after completion") -> [success: bb8, unwind unreachable]; ++ } ++ ++ bb9: { ++ unreachable; ++ } ++ ++ bb10: { ++ nop; ++ (((*_13) as variant#3).0: Foo) = Foo(const 5_i32); ++ nop; ++ (((*_13) as variant#3).1: Bar) = Bar(const 6_i32); ++ StorageLive(_5); ++ StorageLive(_6); ++ _6 = (); ++ _0 = CoroutineState::<(), ()>::Yielded(move _6); ++ StorageDead(_5); ++ StorageDead(_6); ++ discriminant((*_13)) = 3; ++ return; + } + } + diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff new file mode 100644 index 0000000000000..fa89df127094a --- /dev/null +++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.panic-unwind.diff @@ -0,0 +1,201 @@ +- // MIR for `main::{closure#0}` before StateTransform ++ // MIR for `main::{closure#0}` after StateTransform + +- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () +- yields () +- { +- let mut _0: (); ++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}>, _2: ()) -> CoroutineState<(), ()> { ++ coroutine layout { ++ field _s0: Foo; ++ field _s1: Bar; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0, _s1], ++ } ++ storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s0, _s1), (_s1, _s0), (_s1, _s1)} ++ } ++ coroutine debug a => _s0; ++ let mut _0: std::ops::CoroutineState<(), ()>; + let _3: Foo; + let _5: (); + let mut _6: (); + let _7: (); + let mut _8: Foo; + let _9: (); + let mut _10: Bar; ++ let mut _11: (); ++ let mut _12: u32; ++ let mut _13: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}; + scope 1 { +- debug a => _3; ++ debug a => (((*_13) as variant#3).0: Foo); ++ coroutine debug b => _s1; + let _4: Bar; + scope 2 { +- debug b => _4; ++ debug b => (((*_13) as variant#3).1: Bar); + } + } + + 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]; ++ _13 = copy (_1.0: &mut {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}); ++ _12 = discriminant((*_13)); ++ switchInt(move _12) -> [0: bb18, 1: bb16, 2: bb15, 3: bb14, otherwise: bb17]; + } + + bb1: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_7); + StorageLive(_8); +- _8 = move _3; +- _7 = take::(move _8) -> [return: bb2, unwind: bb10]; ++ _8 = move (((*_13) as variant#3).0: Foo); ++ _7 = take::(move _8) -> [return: bb2, unwind: bb7]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_9); + StorageLive(_10); +- _10 = move _4; +- _9 = take::(move _10) -> [return: bb3, unwind: bb9]; ++ _10 = move (((*_13) as variant#3).1: Bar); ++ _9 = take::(move _10) -> [return: bb3, unwind: bb6]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); +- _0 = const (); +- StorageDead(_4); ++ _11 = const (); ++ nop; + goto -> bb4; + } + + bb4: { +- StorageDead(_3); +- drop(_1) -> [return: bb5, unwind: bb14]; ++ nop; ++ goto -> bb12; + } + + bb5: { ++ _0 = CoroutineState::<(), ()>::Complete(move _11); ++ discriminant((*_13)) = 1; + return; + } + +- bb6: { +- StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); +- drop(_3) -> [return: bb7, unwind: bb15]; ++ bb6 (cleanup): { ++ StorageDead(_10); ++ StorageDead(_9); ++ goto -> bb9; + } + +- bb7: { +- StorageDead(_3); +- drop(_1) -> [return: bb8, unwind: bb14]; ++ bb7 (cleanup): { ++ goto -> bb8; + } + +- bb8: { +- coroutine_drop; ++ bb8 (cleanup): { ++ StorageDead(_8); ++ StorageDead(_7); ++ goto -> bb9; + } + + bb9 (cleanup): { +- StorageDead(_10); +- StorageDead(_9); +- goto -> bb12; ++ nop; ++ goto -> bb10; + } + + bb10 (cleanup): { ++ nop; + goto -> bb11; + } + + bb11 (cleanup): { +- StorageDead(_8); +- StorageDead(_7); +- goto -> bb12; ++ goto -> bb13; + } + +- bb12 (cleanup): { +- StorageDead(_4); +- goto -> bb13; ++ bb12: { ++ goto -> bb5; + } + + bb13 (cleanup): { +- StorageDead(_3); +- drop(_1) -> [return: bb14, unwind terminate(cleanup)]; ++ discriminant((*_13)) = 2; ++ resume; + } + +- bb14 (cleanup): { +- resume; ++ bb14: { ++ StorageLive(_5); ++ StorageLive(_6); ++ _5 = move _2; ++ goto -> bb1; + } + +- bb15 (cleanup): { +- StorageDead(_3); +- drop(_1) -> [return: bb14, unwind terminate(cleanup)]; ++ bb15: { ++ assert(const false, "coroutine resumed after panicking") -> [success: bb15, unwind continue]; ++ } ++ ++ bb16: { ++ assert(const false, "coroutine resumed after completion") -> [success: bb16, unwind continue]; ++ } ++ ++ bb17: { ++ unreachable; ++ } ++ ++ bb18: { ++ nop; ++ (((*_13) as variant#3).0: Foo) = Foo(const 5_i32); ++ nop; ++ (((*_13) as variant#3).1: Bar) = Bar(const 6_i32); ++ StorageLive(_5); ++ StorageLive(_6); ++ _6 = (); ++ _0 = CoroutineState::<(), ()>::Yielded(move _6); ++ StorageDead(_5); ++ StorageDead(_6); ++ discriminant((*_13)) = 3; ++ return; + } + } + diff --git a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs index 0537aedcf230b..1267f7248bc17 100644 --- a/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs +++ b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs @@ -18,7 +18,7 @@ struct Bar(i32); fn take(_x: T) {} -// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir +// EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.diff fn main() { let _gen = #[coroutine] || { diff --git a/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.StateTransform.diff b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.StateTransform.diff new file mode 100644 index 0000000000000..b84e55cac4616 --- /dev/null +++ b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.StateTransform.diff @@ -0,0 +1,98 @@ +- // MIR for `main::{closure#0}` before StateTransform ++ // MIR for `main::{closure#0}` after StateTransform + +- fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13}, _2: u8) -> () +- yields () +- { ++ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13}>, _2: u8) -> CoroutineState<(), ()> { ++ coroutine layout { ++ field _s0: HasDrop; ++ variant_fields = { ++ Unresumed(0): [], ++ Returned (1): [], ++ Panicked (2): [], ++ Suspend0 (3): [_s0], ++ } ++ storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} ++ } + debug _x => _2; +- let mut _0: (); ++ coroutine debug _d => _s0; ++ 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:20:5: 20:13}; + scope 1 { +- debug _d => _3; ++ debug _d => (((*_11) as variant#3).0: HasDrop); + } + + bb0: { +- StorageLive(_3); +- _3 = HasDrop; +- StorageLive(_4); +- goto -> bb1; ++ _11 = copy (_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:5: 20:13}); ++ _10 = discriminant((*_11)); ++ switchInt(move _10) -> [0: bb6, 3: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_6); + StorageLive(_7); + _7 = (); +- _6 = yield(move _7) -> [resume: bb2, drop: bb4]; ++ _0 = CoroutineState::<(), ()>::Yielded(move _7); ++ StorageDead(_4); ++ StorageDead(_6); ++ StorageDead(_7); ++ discriminant((*_11)) = 3; ++ return; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + _8 = callee() -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_8); + _5 = const (); + goto -> bb1; + } + + bb4: { +- StorageDead(_7); +- StorageDead(_6); +- StorageDead(_4); +- drop(_3) -> [return: bb5, unwind unreachable]; ++ StorageLive(_4); ++ StorageLive(_6); ++ StorageLive(_7); ++ _6 = move _2; ++ goto -> bb2; + } + + bb5: { +- StorageDead(_3); +- drop(_1) -> [return: bb6, unwind unreachable]; ++ unreachable; + } + + bb6: { +- coroutine_drop; ++ nop; ++ (((*_11) as variant#3).0: HasDrop) = HasDrop; ++ StorageLive(_4); ++ goto -> bb1; + } + } + diff --git a/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir deleted file mode 100644 index e5667215d54fd..0000000000000 --- a/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ /dev/null @@ -1,79 +0,0 @@ -// MIR for `main::{closure#0}` 0 coroutine_resume - -fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> { - coroutine layout { - field _s0: HasDrop; - variant_fields = { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - } - storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} - } - debug _x => _2; - coroutine debug _d => _s0; - 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}; - scope 1 { - debug _d => (((*_11) 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]; - } - - bb1: { - nop; - (((*_11) as variant#3).0: HasDrop) = HasDrop; - StorageLive(_4); - goto -> bb2; - } - - bb2: { - StorageLive(_6); - StorageLive(_7); - _7 = (); - _0 = CoroutineState::<(), ()>::Yielded(move _7); - StorageDead(_4); - StorageDead(_6); - StorageDead(_7); - discriminant((*_11)) = 3; - return; - } - - bb3: { - StorageDead(_7); - StorageDead(_6); - StorageLive(_8); - _8 = callee() -> [return: bb4, unwind unreachable]; - } - - bb4: { - StorageDead(_8); - _5 = const (); - goto -> bb2; - } - - bb5: { - StorageLive(_4); - StorageLive(_6); - StorageLive(_7); - _6 = move _2; - goto -> bb3; - } - - bb6: { - unreachable; - } -} diff --git a/tests/mir-opt/coroutine/coroutine_tiny.rs b/tests/mir-opt/coroutine/coroutine_tiny.rs index b92628aebf96a..2f3a7744bd603 100644 --- a/tests/mir-opt/coroutine/coroutine_tiny.rs +++ b/tests/mir-opt/coroutine/coroutine_tiny.rs @@ -1,4 +1,3 @@ -//@ skip-filecheck //! Tests that coroutines that cannot return or unwind don't have unnecessary //! panic branches. @@ -15,7 +14,7 @@ impl Drop for HasDrop { fn callee() {} -// EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +// EMIT_MIR coroutine_tiny.main-{closure#0}.StateTransform.diff fn main() { let _gen = #[coroutine] |_x: u8| { @@ -26,3 +25,6 @@ fn main() { } }; } + +// CHECK-NOT: panic +// CHECK-NOT: cleanup diff --git a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index f8ef70bd6c9ce..617f2ad463ed3 100644 --- a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -47,42 +47,42 @@ + let _26: (); + scope 9 { + } -+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ scope 11 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } -+ scope 13 (inlined as Future>::poll) { -+ 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 _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 _41: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 12 (inlined as Future>::poll) { ++ let mut _33: (); ++ let mut _34: std::option::Option<()>; ++ let mut _35: &mut std::option::Option<()>; ++ let mut _36: &mut std::future::Ready<()>; ++ let mut _37: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 13 (inlined > as DerefMut>::deref_mut) { ++ let mut _38: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; ++ let mut _39: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 14 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { ++ let mut _40: &mut &mut std::future::Ready<()>; ++ scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } + } -+ scope 17 (inlined Option::<()>::take) { -+ let mut _42: std::option::Option<()>; -+ scope 18 (inlined std::mem::replace::>) { -+ scope 19 { ++ scope 16 (inlined Option::<()>::take) { ++ let mut _41: std::option::Option<()>; ++ scope 17 (inlined std::mem::replace::>) { ++ scope 18 { + } + } + } -+ scope 20 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _43: isize; -+ let mut _44: !; -+ scope 21 { ++ scope 19 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _42: isize; ++ let mut _43: !; ++ scope 20 { + } + } + } + } -+ scope 10 (inlined ready::<()>) { -+ let mut _33: std::option::Option<()>; ++ scope 10 (inlined as IntoFuture>::into_future) { + } -+ scope 11 (inlined as IntoFuture>::into_future) { ++ scope 21 (inlined ready::<()>) { ++ let mut _44: std::option::Option<()>; + } + } + } @@ -127,7 +127,7 @@ + StorageLive(_32); + _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]; ++ switchInt(move _31) -> [0: bb10, 1: bb9, 3: bb8, otherwise: bb4]; } - bb3: { @@ -154,25 +154,6 @@ } + bb3: { -+ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); -+ StorageLive(_12); -+ StorageLive(_13); -+ StorageLive(_14); -+ _14 = (); -+ StorageLive(_33); -+ _33 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _33); -+ StorageDead(_33); -+ StorageDead(_14); -+ _12 = move _13; -+ StorageDead(_13); -+ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb4; -+ } -+ - bb4: { -- StorageDead(_2); -- return; + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -189,31 +170,33 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); -+ StorageLive(_37); -+ StorageLive(_39); -+ StorageLive(_44); ++ StorageLive(_36); ++ StorageLive(_38); ++ StorageLive(_43); ++ StorageLive(_33); + 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 = no_retag copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageLive(_39); ++ _39 = &raw mut _19; ++ _38 = copy _39 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); ++ StorageDead(_39); ++ _36 = no_retag copy ((*_38).0: &mut std::future::Ready<()>); ++ StorageLive(_41); ++ _41 = Option::<()>::None; ++ _34 = copy ((*_36).0: std::option::Option<()>); ++ ((*_36).0: std::option::Option<()>) = move _41; ++ StorageDead(_41); + StorageLive(_42); -+ _42 = Option::<()>::None; -+ _35 = copy ((*_37).0: std::option::Option<()>); -+ ((*_37).0: std::option::Option<()>) = move _42; -+ StorageDead(_42); -+ StorageLive(_43); -+ _43 = discriminant(_35); -+ switchInt(move _43) -> [0: bb11, 1: bb12, otherwise: bb5]; - } ++ _42 = discriminant(_34); ++ switchInt(move _42) -> [0: bb11, 1: bb12, otherwise: bb4]; ++ } + -+ bb5: { + bb4: { +- StorageDead(_2); +- return; + unreachable; -+ } + } + -+ bb6: { ++ bb5: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -230,7 +213,7 @@ + goto -> bb2; + } + -+ bb7: { ++ bb6: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -240,16 +223,16 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb7, unwind unreachable]; + } + -+ bb8: { ++ bb7: { + _7 = Poll::<()>::Ready(move _30); + discriminant((*_32)) = 1; + goto -> bb2; + } + -+ bb9: { ++ bb8: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -258,30 +241,47 @@ + _9 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb4; ++ goto -> bb3; ++ } ++ ++ bb9: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb9, unwind unreachable]; + } + + bb10: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb10, unwind unreachable]; ++ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = (); ++ StorageLive(_44); ++ _44 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _44); ++ StorageDead(_44); ++ StorageDead(_14); ++ _12 = move _13; ++ StorageDead(_13); ++ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; ++ goto -> bb3; + } + + bb11: { -+ _44 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ _43 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; + } + + bb12: { -+ _34 = move ((_35 as Some).0: ()); -+ StorageDead(_43); -+ StorageDead(_35); -+ _18 = Poll::<()>::Ready(move _34); ++ _33 = move ((_34 as Some).0: ()); ++ StorageDead(_42); + StorageDead(_34); -+ StorageDead(_44); -+ StorageDead(_39); -+ StorageDead(_37); ++ _18 = Poll::<()>::Ready(move _33); ++ StorageDead(_33); ++ StorageDead(_43); ++ StorageDead(_38); ++ StorageDead(_36); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5]; ++ switchInt(move _25) -> [0: bb6, 1: bb5, otherwise: bb4]; + } + } + diff --git a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 18be10c534ec4..f12462a4d2b34 100644 --- a/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -47,42 +47,42 @@ + let _26: (); + scope 9 { + } -+ scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ scope 11 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } -+ scope 13 (inlined as Future>::poll) { -+ 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 _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 _41: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 12 (inlined as Future>::poll) { ++ let mut _33: (); ++ let mut _34: std::option::Option<()>; ++ let mut _35: &mut std::option::Option<()>; ++ let mut _36: &mut std::future::Ready<()>; ++ let mut _37: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 13 (inlined > as DerefMut>::deref_mut) { ++ let mut _38: *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>>; ++ let mut _39: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 14 (inlined > as pin::helper::PinDerefMutHelper>::deref_mut) { ++ let mut _40: &mut &mut std::future::Ready<()>; ++ scope 15 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } + } -+ scope 17 (inlined Option::<()>::take) { -+ let mut _42: std::option::Option<()>; -+ scope 18 (inlined std::mem::replace::>) { -+ scope 19 { ++ scope 16 (inlined Option::<()>::take) { ++ let mut _41: std::option::Option<()>; ++ scope 17 (inlined std::mem::replace::>) { ++ scope 18 { + } + } + } -+ scope 20 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _43: isize; -+ let mut _44: !; -+ scope 21 { ++ scope 19 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _42: isize; ++ let mut _43: !; ++ scope 20 { + } + } + } + } -+ scope 10 (inlined ready::<()>) { -+ let mut _33: std::option::Option<()>; ++ scope 10 (inlined as IntoFuture>::into_future) { + } -+ scope 11 (inlined as IntoFuture>::into_future) { ++ scope 21 (inlined ready::<()>) { ++ let mut _44: std::option::Option<()>; + } + } + } @@ -127,7 +127,7 @@ + StorageLive(_32); + _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]; ++ switchInt(move _31) -> [0: bb15, 1: bb14, 2: bb13, 3: bb12, otherwise: bb6]; } - bb3: { @@ -165,25 +165,6 @@ - StorageDead(_2); - return; + bb5: { -+ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); -+ StorageLive(_12); -+ StorageLive(_13); -+ StorageLive(_14); -+ _14 = (); -+ StorageLive(_33); -+ _33 = Option::<()>::Some(copy _14); -+ _13 = std::future::Ready::<()>(move _33); -+ StorageDead(_33); -+ StorageDead(_14); -+ _12 = move _13; -+ StorageDead(_13); -+ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb6; - } - -- bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; -+ bb6: { + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -200,33 +181,35 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); -+ StorageLive(_37); -+ StorageLive(_39); -+ StorageLive(_44); ++ StorageLive(_36); ++ StorageLive(_38); ++ StorageLive(_43); ++ StorageLive(_33); + 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 = no_retag copy ((*_39).0: &mut std::future::Ready<()>); ++ StorageLive(_39); ++ _39 = &raw mut _19; ++ _38 = copy _39 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); ++ StorageDead(_39); ++ _36 = no_retag copy ((*_38).0: &mut std::future::Ready<()>); ++ StorageLive(_41); ++ _41 = Option::<()>::None; ++ _34 = copy ((*_36).0: std::option::Option<()>); ++ ((*_36).0: std::option::Option<()>) = move _41; ++ StorageDead(_41); + StorageLive(_42); -+ _42 = Option::<()>::None; -+ _35 = copy ((*_37).0: std::option::Option<()>); -+ ((*_37).0: std::option::Option<()>) = move _42; -+ StorageDead(_42); -+ StorageLive(_43); -+ _43 = discriminant(_35); -+ switchInt(move _43) -> [0: bb16, 1: bb17, otherwise: bb7]; ++ _42 = discriminant(_34); ++ switchInt(move _42) -> [0: bb16, 1: bb17, otherwise: bb6]; + } + +- bb5 (cleanup): { +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; ++ bb6: { ++ unreachable; } - bb6 (cleanup): { - resume; + bb7: { -+ unreachable; - } -+ -+ bb8: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -241,9 +224,9 @@ + StorageDead(_29); + discriminant((*_32)) = 3; + goto -> bb4; -+ } + } + -+ bb9: { ++ bb8: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -253,16 +236,16 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb9, unwind: bb11]; + } + -+ bb10: { ++ bb9: { + _7 = Poll::<()>::Ready(move _30); + discriminant((*_32)) = 1; + goto -> bb4; + } + -+ bb11 (cleanup): { ++ bb10 (cleanup): { + StorageDead(_22); + StorageDead(_19); + StorageDead(_23); @@ -270,15 +253,15 @@ + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; ++ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind terminate(cleanup)]; + } + -+ bb12 (cleanup): { ++ bb11 (cleanup): { + discriminant((*_32)) = 2; + goto -> bb2; + } + -+ bb13: { ++ bb12: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -287,34 +270,51 @@ + _9 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb6; ++ goto -> bb5; ++ } ++ ++ bb13: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb13, unwind: bb2]; + } + + bb14: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb14, unwind: bb2]; ++ assert(const false, "`async fn` resumed after completion") -> [success: bb14, unwind: bb2]; + } + + bb15: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb15, unwind: bb2]; ++ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = (); ++ StorageLive(_44); ++ _44 = Option::<()>::Some(copy _14); ++ _13 = std::future::Ready::<()>(move _44); ++ StorageDead(_44); ++ StorageDead(_14); ++ _12 = move _13; ++ StorageDead(_13); ++ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; ++ goto -> bb5; + } + + bb16: { -+ _44 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ _43 = option::expect_failed(const "`Ready` polled after completion") -> bb10; + } + + bb17: { -+ _34 = move ((_35 as Some).0: ()); -+ StorageDead(_43); -+ StorageDead(_35); -+ _18 = Poll::<()>::Ready(move _34); ++ _33 = move ((_34 as Some).0: ()); ++ StorageDead(_42); + StorageDead(_34); -+ StorageDead(_44); -+ StorageDead(_39); -+ StorageDead(_37); ++ _18 = Poll::<()>::Ready(move _33); ++ StorageDead(_33); ++ StorageDead(_43); ++ StorageDead(_38); ++ StorageDead(_36); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7]; ++ switchInt(move _25) -> [0: bb8, 1: bb7, otherwise: bb6]; + } + } + diff --git a/tests/ui/force-inlining/deny-async.stderr b/tests/ui/force-inlining/deny-async.stderr index d6516ed875c21..bd24bc694e8ae 100644 --- a/tests/ui/force-inlining/deny-async.stderr +++ b/tests/ui/force-inlining/deny-async.stderr @@ -20,14 +20,6 @@ LL | pub fn callee_justified() { | = note: incompatible due to: #[rustc_no_mir_inline] -error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined - --> $DIR/deny-async.rs:22:5 - | -LL | callee(); - | ^^^^^^^^ ...`callee` called here - | - = note: could not be inlined due to: #[rustc_no_mir_inline] - error: `callee_justified` could not be inlined into `async_caller::{closure#0}` but is required to be inlined --> $DIR/deny-async.rs:24:5 | @@ -37,5 +29,13 @@ LL | callee_justified(); = note: could not be inlined due to: #[rustc_no_mir_inline] = note: `callee_justified` is required to be inlined to: the test requires it +error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined + --> $DIR/deny-async.rs:22:5 + | +LL | callee(); + | ^^^^^^^^ ...`callee` called here + | + = note: could not be inlined due to: #[rustc_no_mir_inline] + error: aborting due to 4 previous errors diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index 3aca86ae66935..6dbc1ddf2aad9 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -48,9 +48,15 @@ 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: bb3, 1: bb1, otherwise: bb2]; } bb1: { + assert(false, `async fn` resumed after completion) -> [success: bb1, unwind unreachable]; + } + bb2: { + unreachable; + } + bb3: { StorageLive(_3); _4 = no_retag ((*_7).0: &i32); _3 = (*_4); @@ -60,12 +66,6 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo discriminant((*_7)) = 1; return; } - bb2: { - assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; - } - bb3: { - unreachable; - } } fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> { let mut _0: Poll<()>; @@ -80,9 +80,15 @@ 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: bb3, 1: bb1, otherwise: bb2]; } bb1: { + assert(false, `async fn` resumed after completion) -> [success: bb1, unwind unreachable]; + } + bb2: { + unreachable; + } + bb3: { StorageLive(_3); _4 = no_retag ((*_7).0: &i32); _3 = (*_4); @@ -92,10 +98,4 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c discriminant((*_7)) = 1; return; } - bb2: { - assert(false, `async fn` resumed after completion) -> [success: bb2, unwind unreachable]; - } - bb3: { - unreachable; - } } From f6a5b0b0c07d00673e89ac537ebe850538837428 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Fri, 29 May 2026 19:59:02 +0000 Subject: [PATCH 5/5] Review nits. --- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 1f8efa72ea867..7bae4768bf46a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -430,8 +430,8 @@ fn write_scope_tree( // Coroutine debuginfo. if let Some(layout) = body.coroutine_layout_raw() { for (field, name) in layout.field_names.iter_enumerated() { + let source_info = layout.field_tys[field].source_info; if let Some(name) = name - && let source_info = layout.field_tys[field].source_info && source_info.scope == parent { let indented_debug_info = diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index a00fad4bd599a..87db4550d4f10 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1183,9 +1183,8 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { return false; } - // Unwinds can only start at certain terminators. + // If we don't find an unwinding terminator, the function cannot unwind. body.basic_blocks.iter().any(|block| block.terminator().unwind().is_some()) - // If we didn't find an unwinding terminator, the function cannot unwind. } // Poison the coroutine when it unwinds