safe transmute: support Variants::Single enums
Previously, the implementation of `Tree::from_enum` incorrectly treated enums with `Variants::Single` and `Variants::Multiple` identically. This is incorrect for `Variants::Single` enums, which delegate their layout to that of a variant with a particular index (or no variant at all if the enum is empty). This flaw manifested first as an ICE. `Tree::from_enum` attempted to compute the tag of variants other than the one at `Variants::Single`'s `index`, and fell afoul of a sanity-checking assertion in `compiler/rustc_const_eval/src/interpret/discriminant.rs`. This assertion is non-load-bearing, and can be removed; the routine its in is well-behaved even without it. With the assertion removed, the proximate issue becomes apparent: calling `Tree::from_variant` on a variant that does not exist is ill-defined. A sanity check the given variant has `FieldShapes::Arbitrary` fails, and the analysis is (correctly) aborted with `Err::NotYetSupported`. This commit corrects this chain of failures by ensuring that `Tree::from_variant` is not called on variants that are, as far as layout is concerned, nonexistent. Specifically, the implementation of `Tree::from_enum` is now partitioned into three cases: 1. enums that are uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple inhabited variants `Tree::from_variant` is now only invoked in the third case. In the first case, `Tree::uninhabited()` is produced. In the second case, the layout is delegated to `Variants::Single`'s index. Fixes #125811
This commit is contained in:
parent
1d43fbbc73
commit
fb662f2126
4 changed files with 81 additions and 59 deletions
26
tests/ui/transmutability/enums/uninhabited_optimization.rs
Normal file
26
tests/ui/transmutability/enums/uninhabited_optimization.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//@ check-pass
|
||||
//! Tests that we do not regress rust-lang/rust#125811
|
||||
#![feature(transmutability)]
|
||||
|
||||
fn assert_transmutable<T>()
|
||||
where
|
||||
(): std::mem::BikeshedIntrinsicFrom<T>
|
||||
{}
|
||||
|
||||
enum Uninhabited {}
|
||||
|
||||
enum SingleInhabited {
|
||||
X,
|
||||
Y(Uninhabited)
|
||||
}
|
||||
|
||||
enum SingleUninhabited {
|
||||
X(Uninhabited),
|
||||
Y(Uninhabited),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_transmutable::<Uninhabited>();
|
||||
assert_transmutable::<SingleInhabited>();
|
||||
assert_transmutable::<SingleUninhabited>();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue