Rollup merge of #118871 - tmiasko:coroutine-maybe-uninit-fields, r=compiler-errors
Coroutine variant fields can be uninitialized Wrap coroutine variant fields in MaybeUninit to indicate that they might be uninitialized. Otherwise an uninhabited field will make the entire variant uninhabited and introduce undefined behaviour. The analogous issue in the prefix of coroutine layout was addressed by 6fae7f807146e400fa2bbd1c44768d9bcaa57c4c.
This commit is contained in:
commit
1dd36119d0
@ -831,7 +831,10 @@ fn coroutine_layout<'tcx>(
|
||||
Assigned(_) => bug!("assignment does not match variant"),
|
||||
Ineligible(_) => false,
|
||||
})
|
||||
.map(|local| subst_field(info.field_tys[*local].ty));
|
||||
.map(|local| {
|
||||
let field_ty = subst_field(info.field_tys[*local].ty);
|
||||
Ty::new_maybe_uninit(tcx, field_ty)
|
||||
});
|
||||
|
||||
let mut variant = univariant_uninterned(
|
||||
cx,
|
||||
|
@ -52,10 +52,16 @@ print-type-size variant `Panicked`: 1024 bytes
|
||||
print-type-size upvar `.arg`: 1024 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Ready`: 0 bytes
|
||||
|
@ -1,7 +1,9 @@
|
||||
error[E0391]: cycle detected when computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`
|
||||
error[E0391]: cycle detected when computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`
|
||||
|
|
||||
= note: ...which requires computing layout of `<<A as First>::Second as Second>::{opaque#0}`...
|
||||
= note: ...which again requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`, completing the cycle
|
||||
= note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`...
|
||||
= note: ...which requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`...
|
||||
= note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<<<A as First>::Second as Second>::{opaque#0}>`...
|
||||
= note: ...which again requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`, completing the cycle
|
||||
= note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:6:13: 8:6}`
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
|
37
tests/ui/coroutine/uninhabited-field.rs
Normal file
37
tests/ui/coroutine/uninhabited-field.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Test that uninhabited saved local doesn't make the entire variant uninhabited.
|
||||
// run-pass
|
||||
#![allow(unused)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(coroutine_trait)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(never_type)]
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::ops::Coroutine;
|
||||
use std::ops::CoroutineState;
|
||||
use std::pin::Pin;
|
||||
|
||||
fn conjure<T>() -> T { loop {} }
|
||||
|
||||
fn run<T>(x: bool, y: bool) {
|
||||
let mut c = || {
|
||||
if x {
|
||||
let a : T;
|
||||
if y {
|
||||
a = conjure::<T>();
|
||||
}
|
||||
yield ();
|
||||
} else {
|
||||
let a : T;
|
||||
if y {
|
||||
a = conjure::<T>();
|
||||
}
|
||||
yield ();
|
||||
}
|
||||
};
|
||||
assert_matches!(Pin::new(&mut c).resume(()), CoroutineState::Yielded(()));
|
||||
assert_matches!(Pin::new(&mut c).resume(()), CoroutineState::Complete(()));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
run::<!>(false, false);
|
||||
}
|
@ -9,3 +9,9 @@ print-type-size padding: 3 bytes
|
||||
print-type-size local `.z`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
print-type-size variant `Panicked`: 0 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<i32>`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size field `.value`: 4 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<i32>`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size variant `MaybeUninit`: 4 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 4 bytes
|
||||
|
Loading…
x
Reference in New Issue
Block a user