summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-07-04 18:16:22 +0200
committerGitHub <noreply@github.com>2024-07-04 18:16:22 +0200
commitf0a0f8f7e8adae3f5abf945af9c9f3b2f95af43b (patch)
tree7e4c968a3cf59040a841a1648ff576be464ec65e /compiler
parente2cf31a6148725bde4ea48acf1e4fe72675257a2 (diff)
parent8a3c07afbe94ff892b9fef982dea3ba1af7c7a5a (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.rs4
-rw-r--r--compiler/rustc_abi/src/lib.rs2
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