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
6fae7f8071
.
This commit is contained in:
parent
5b8bc568d2
commit
a48cebc4b8
5 changed files with 58 additions and 4 deletions
|
@ -831,7 +831,10 @@ fn coroutine_layout<'tcx>(
|
||||||
Assigned(_) => bug!("assignment does not match variant"),
|
Assigned(_) => bug!("assignment does not match variant"),
|
||||||
Ineligible(_) => false,
|
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(
|
let mut variant = univariant_uninterned(
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -52,10 +52,16 @@ print-type-size variant `Panicked`: 1024 bytes
|
||||||
print-type-size upvar `.arg`: 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 type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
|
||||||
print-type-size field `.value`: 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 type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
|
||||||
print-type-size variant `MaybeUninit`: 1 bytes
|
print-type-size variant `MaybeUninit`: 1 bytes
|
||||||
print-type-size field `.uninit`: 0 bytes
|
print-type-size field `.uninit`: 0 bytes
|
||||||
print-type-size field `.value`: 1 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 type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
|
||||||
print-type-size discriminant: 1 bytes
|
print-type-size discriminant: 1 bytes
|
||||||
print-type-size variant `Ready`: 0 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 requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}>`...
|
||||||
= 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 `{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: 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
|
= 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 local `.z`: 4 bytes, alignment: 4 bytes
|
||||||
print-type-size variant `Returned`: 0 bytes
|
print-type-size variant `Returned`: 0 bytes
|
||||||
print-type-size variant `Panicked`: 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…
Add table
Add a link
Reference in a new issue