Add test.

This commit is contained in:
Camille Gillot 2025-09-14 19:08:16 +00:00
parent a9d0a6f155
commit 40d879a47f
7 changed files with 453 additions and 11 deletions

View file

@ -471,7 +471,7 @@ impl<'tcx> Body<'tcx> {
/// Returns an iterator over all function arguments.
#[inline]
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator + use<> {
(1..self.arg_count + 1).map(Local::new)
}

View file

@ -17,7 +17,7 @@ use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
rustc_index::newtype_index! {
#[derive(HashStable)]
#[encodable]
#[debug_format = "_{}"]
#[debug_format = "_s{}"]
pub struct CoroutineSavedLocal {}
}

View file

@ -1,7 +1,7 @@
// MIR for `b::{closure#0}` 0 coroutine_resume
/* coroutine_layout = CoroutineLayout {
field_tys: {
_0: CoroutineSavedTy {
_s0: CoroutineSavedTy {
ty: Coroutine(
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
[
@ -18,7 +18,7 @@
},
ignore_for_traits: false,
},
_1: CoroutineSavedTy {
_s1: CoroutineSavedTy {
ty: Coroutine(
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
[
@ -40,12 +40,12 @@
Unresumed(0): [],
Returned (1): [],
Panicked (2): [],
Suspend0 (3): [_0],
Suspend1 (4): [_1],
Suspend0 (3): [_s0],
Suspend1 (4): [_s1],
},
storage_conflicts: BitMatrix(2x2) {
(_0, _0),
(_1, _1),
(_s0, _s0),
(_s1, _s1),
},
} */

View file

@ -0,0 +1,208 @@
// 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:17:32: 17:35 (#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:17:31: 17:44}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44})) as variant#4).0: std::string::String);
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 _17: std::string::String;
let mut _18: u32;
let mut _19: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
let mut _26: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44};
bb0: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_18 = discriminant((*_19));
switchInt(move _18) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
(((*_20) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_6 = &(((*_21) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
bb2: {
StorageDead(_6);
StorageLive(_7);
_7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
}
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);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_22)) = 3;
return;
}
bb5: {
goto -> bb6;
}
bb6: {
StorageDead(_4);
drop(_3) -> [return: bb7, unwind unreachable];
}
bb7: {
StorageDead(_3);
StorageLive(_8);
StorageLive(_9);
StorageLive(_10);
StorageLive(_11);
_11 = const "second";
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
_13 = &(((*_23) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
bb8: {
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);
_15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
}
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);
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_24)) = 4;
return;
}
bb11: {
goto -> bb12;
}
bb12: {
StorageDead(_9);
drop(_8) -> [return: bb13, unwind unreachable];
}
bb13: {
StorageDead(_15);
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
drop((((*_25) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
bb14: {
goto -> bb16;
}
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_26 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:17:31: 17:44});
discriminant((*_26)) = 1;
return;
}
bb16: {
goto -> bb15;
}
bb17: {
StorageLive(_3);
StorageLive(_4);
_3 = move _2;
goto -> bb5;
}
bb18: {
StorageLive(_8);
StorageLive(_9);
StorageLive(_11);
StorageLive(_15);
_8 = move _2;
goto -> bb11;
}
bb19: {
assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
}
bb20: {
unreachable;
}
}
ALLOC0 (size: 6, align: 1) {
73 65 63 6f 6e 64 second
}
ALLOC1 (size: 5, align: 1) {
66 69 72 73 74 first
}

View file

@ -0,0 +1,208 @@
// 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:22:54: 22:57 (#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:22:53: 22:66}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> {
debug arg => (((*(_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66})) as variant#4).0: std::string::String);
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 _17: std::string::String;
let mut _18: u32;
let mut _19: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _20: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _21: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _22: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _23: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _24: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _25: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
let mut _26: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66};
bb0: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_18 = discriminant((*_19));
switchInt(move _18) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
(((*_20) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_6 = &(((*_21) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
bb2: {
StorageDead(_6);
StorageLive(_7);
_7 = Location::<'_>::caller() -> [return: bb3, unwind unreachable];
}
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);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_22)) = 3;
return;
}
bb5: {
goto -> bb6;
}
bb6: {
StorageDead(_4);
drop(_3) -> [return: bb7, unwind unreachable];
}
bb7: {
StorageDead(_3);
StorageLive(_8);
StorageLive(_9);
StorageLive(_10);
StorageLive(_11);
_11 = const "second";
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
_13 = &(((*_23) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
bb8: {
StorageDead(_13);
StorageLive(_14);
StorageLive(_15);
_15 = Location::<'_>::caller() -> [return: bb9, unwind unreachable];
}
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);
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_24)) = 4;
return;
}
bb11: {
goto -> bb12;
}
bb12: {
StorageDead(_9);
drop(_8) -> [return: bb13, unwind unreachable];
}
bb13: {
StorageDead(_15);
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
drop((((*_25) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
bb14: {
goto -> bb16;
}
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_26 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:22:53: 22:66});
discriminant((*_26)) = 1;
return;
}
bb16: {
goto -> bb15;
}
bb17: {
StorageLive(_3);
StorageLive(_4);
_3 = move _2;
goto -> bb5;
}
bb18: {
StorageLive(_8);
StorageLive(_9);
StorageLive(_11);
StorageLive(_15);
_8 = move _2;
goto -> bb11;
}
bb19: {
assert(const false, "coroutine resumed after completion") -> [success: bb19, unwind unreachable];
}
bb20: {
unreachable;
}
}
ALLOC0 (size: 6, align: 1) {
73 65 63 6f 6e 64 second
}
ALLOC1 (size: 5, align: 1) {
66 69 72 73 74 first
}

View file

@ -0,0 +1,26 @@
// skip-filecheck
//@ edition:2024
//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
#![feature(stmt_expr_attributes)]
#![feature(closure_track_caller)]
#![feature(coroutine_trait)]
#![feature(coroutines)]
use std::ops::{Coroutine, CoroutineState};
use std::pin::Pin;
use std::panic::Location;
// EMIT_MIR coroutine.main-{closure#0}.StateTransform.after.mir
// EMIT_MIR coroutine.main-{closure#1}.StateTransform.after.mir
fn main() {
let simple = #[coroutine] |arg: String| {
yield ("first", arg.clone(), Location::caller());
yield ("second", arg.clone(), Location::caller());
};
let track_caller = #[track_caller] #[coroutine] |arg: String| {
yield ("first", arg.clone(), Location::caller());
yield ("second", arg.clone(), Location::caller());
};
}

View file

@ -1,7 +1,7 @@
// MIR for `main::{closure#0}` 0 coroutine_resume
/* coroutine_layout = CoroutineLayout {
field_tys: {
_0: CoroutineSavedTy {
_s0: CoroutineSavedTy {
ty: HasDrop,
source_info: SourceInfo {
span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0),
@ -14,10 +14,10 @@
Unresumed(0): [],
Returned (1): [],
Panicked (2): [],
Suspend0 (3): [_0],
Suspend0 (3): [_s0],
},
storage_conflicts: BitMatrix(1x1) {
(_0, _0),
(_s0, _s0),
},
} */