diff options
author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-07-04 18:16:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-04 18:16:22 +0200 |
commit | f0a0f8f7e8adae3f5abf945af9c9f3b2f95af43b (patch) | |
tree | 7e4c968a3cf59040a841a1648ff576be464ec65e /compiler | |
parent | e2cf31a6148725bde4ea48acf1e4fe72675257a2 (diff) | |
parent | 8a3c07afbe94ff892b9fef982dea3ba1af7c7a5a (diff) |
Rollup merge of #123043 - GoldsteinE:fix/repr-c-dead-branches, r=oli-obk
Disable dead variant removal for `#[repr(C)]` enums.
This prevents removing dead branches from a `#[repr(C)]` enum (they now get discriminants allocated as if they were inhabited).
Implementation notes: ABI of something like
```rust
#[repr(C)]
enum Foo {
Foo(!),
}
```
is still `Uninhabited`, but its layout is now computed as if all the branches were inhabited.
This seemed to me like a proper way to do it, especially given that ABI sanity check explicitly asserts that type-level uninhabitedness implies ABI uninhabitedness.
This probably needs some sort of FCP (given that it changes `#[repr(C)]` layout, which is a stable guarantee), but I’m not sure how to call for one or which team is the most relevant.
See https://github.com/rust-lang/unsafe-code-guidelines/issues/500.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/rustc_abi/src/layout.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_abi/src/lib.rs | 2 |
2 files changed, 3 insertions, 3 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 9165b4f2df3..197dd7f9c9e 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -186,7 +186,7 @@ pub trait LayoutCalculator { let (present_first, present_second) = { let mut present_variants = variants .iter_enumerated() - .filter_map(|(i, v)| if absent(v) { None } else { Some(i) }); + .filter_map(|(i, v)| if !repr.c() && absent(v) { None } else { Some(i) }); (present_variants.next(), present_variants.next()) }; let present_first = match present_first { @@ -621,7 +621,7 @@ where let discr_type = repr.discr_type(); let bits = Integer::from_attr(dl, discr_type).size().bits(); for (i, mut val) in discriminants { - if variants[i].iter().any(|f| f.abi.is_uninhabited()) { + if !repr.c() && variants[i].iter().any(|f| f.abi.is_uninhabited()) { continue; } if discr_type.is_signed() { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 31c66a56bea..78332d66f03 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1429,7 +1429,7 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { index: VariantIdx }, - /// Enum-likes with more than one inhabited variant: each variant comes with + /// Enum-likes with more than one variant: each variant comes with /// a *discriminant* (usually the same as the variant index but the user can /// assign explicit discriminant values). That discriminant is encoded /// as a *tag* on the machine. The layout of each variant is |