From 9f4c9155d4535e08a3148e792711447e44541cd1 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 20 Oct 2024 01:45:15 -0700 Subject: [PATCH] compiler: Reject impossible reprs during enum layout --- compiler/rustc_abi/src/layout.rs | 9 +++ compiler/rustc_ty_utils/src/layout.rs | 5 ++ .../ui/layout/thaw-transmute-invalid-enum.rs | 9 ++- .../layout/thaw-transmute-invalid-enum.stderr | 68 +++++++++++++++++++ tests/ui/layout/thaw-validate-invalid-enum.rs | 5 +- .../layout/thaw-validate-invalid-enum.stderr | 29 ++++++++ 6 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 tests/ui/layout/thaw-transmute-invalid-enum.stderr create mode 100644 tests/ui/layout/thaw-validate-invalid-enum.stderr diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 5ce5f14ce57cb..59f42425bb936 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -54,6 +54,9 @@ pub enum LayoutCalculatorError { /// A union had no fields. EmptyUnion, + + /// The fields or variants have irreconcilable reprs + ReprConflict, } impl LayoutCalculatorError { @@ -64,6 +67,7 @@ impl LayoutCalculatorError { } LayoutCalculatorError::SizeOverflow => LayoutCalculatorError::SizeOverflow, LayoutCalculatorError::EmptyUnion => LayoutCalculatorError::EmptyUnion, + LayoutCalculatorError::ReprConflict => LayoutCalculatorError::ReprConflict, } } @@ -77,6 +81,7 @@ impl LayoutCalculatorError { } LayoutCalculatorError::SizeOverflow => "size overflow", LayoutCalculatorError::EmptyUnion => "type is a union with no fields", + LayoutCalculatorError::ReprConflict => "type has an invalid repr", }) } } @@ -514,6 +519,10 @@ impl LayoutCalculator { } let dl = self.cx.data_layout(); + // bail if the enum has an incoherent repr that cannot be computed + if repr.packed() { + return Err(LayoutCalculatorError::ReprConflict); + } let calculate_niche_filling_layout = || -> Option> { if dont_niche_optimize_enum { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index db70a12a4d1c8..38b292afe8d71 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -116,6 +116,11 @@ fn map_error<'tcx>( cx.tcx().dcx().delayed_bug(format!("computed layout of empty union: {ty:?}")); LayoutError::Unknown(ty) } + LayoutCalculatorError::ReprConflict => { + // packed enums are the only known trigger of this, but others might arise + cx.tcx().dcx().delayed_bug(format!("computed impossible repr (packed enum?): {ty:?}")); + LayoutError::Unknown(ty) + } }; error(cx, err) } diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs index 2c9f1a70f4fbf..835dcc049964f 100644 --- a/tests/ui/layout/thaw-transmute-invalid-enum.rs +++ b/tests/ui/layout/thaw-transmute-invalid-enum.rs @@ -1,10 +1,14 @@ -//@ known-bug: rust-lang/rust#126966 +#![crate_type = "lib"] + mod assert { use std::mem::{Assume, TransmuteFrom}; + //~^ ERROR: use of unstable library feature 'transmutability' + //~| ERROR: use of unstable library feature 'transmutability' pub fn is_transmutable() where Dst: TransmuteFrom, + //~^ ERROR: use of unstable library feature 'transmutability' { } } @@ -15,6 +19,7 @@ enum Ox00 { } #[repr(C, packed(2))] +//~^ ERROR: attribute should be applied to a struct enum OxFF { V = 0xFF, } @@ -22,8 +27,10 @@ enum OxFF { fn test() { union Superset { a: Ox00, + //~^ ERROR: field must implement `Copy` b: OxFF, } assert::is_transmutable::(); + //~^ ERROR: cannot find type `Subset` } diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.stderr b/tests/ui/layout/thaw-transmute-invalid-enum.stderr new file mode 100644 index 0000000000000..e6a5399c66b3d --- /dev/null +++ b/tests/ui/layout/thaw-transmute-invalid-enum.stderr @@ -0,0 +1,68 @@ +error[E0412]: cannot find type `Subset` in this scope + --> $DIR/thaw-transmute-invalid-enum.rs:34:41 + | +LL | assert::is_transmutable::(); + | ^^^^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn test() { + | ++++++++ + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/thaw-transmute-invalid-enum.rs:21:11 + | +LL | #[repr(C, packed(2))] + | ^^^^^^^^^ +LL | +LL | / enum OxFF { +LL | | V = 0xFF, +LL | | } + | |_- not a struct or union + +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/thaw-transmute-invalid-enum.rs:4:20 + | +LL | use std::mem::{Assume, TransmuteFrom}; + | ^^^^^^ + | + = note: see issue #99571 for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/thaw-transmute-invalid-enum.rs:4:28 + | +LL | use std::mem::{Assume, TransmuteFrom}; + | ^^^^^^^^^^^^^ + | + = note: see issue #99571 for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/thaw-transmute-invalid-enum.rs:10:14 + | +LL | Dst: TransmuteFrom, + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99571 for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/thaw-transmute-invalid-enum.rs:29:9 + | +LL | a: Ox00, + | ^^^^^^^ + | + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` + | +LL | a: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0412, E0517, E0658, E0740. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/layout/thaw-validate-invalid-enum.rs b/tests/ui/layout/thaw-validate-invalid-enum.rs index 2b7319621440c..51aff7fb556c2 100644 --- a/tests/ui/layout/thaw-validate-invalid-enum.rs +++ b/tests/ui/layout/thaw-validate-invalid-enum.rs @@ -1,7 +1,6 @@ -//@ known-bug: rust-lang/rust#128870 //@ compile-flags: -Zvalidate-mir -#[repr(packed)] +#[repr(packed)] //~ ERROR: attribute should be applied to a struct #[repr(u32)] enum E { A, @@ -12,7 +11,7 @@ enum E { fn main() { union InvalidTag { int: u32, - e: E, + e: E, //~ ERROR: field must implement `Copy` } let _invalid_tag = InvalidTag { int: 4 }; } diff --git a/tests/ui/layout/thaw-validate-invalid-enum.stderr b/tests/ui/layout/thaw-validate-invalid-enum.stderr new file mode 100644 index 0000000000000..9e522cba96aa1 --- /dev/null +++ b/tests/ui/layout/thaw-validate-invalid-enum.stderr @@ -0,0 +1,29 @@ +error[E0517]: attribute should be applied to a struct or union + --> $DIR/thaw-validate-invalid-enum.rs:3:8 + | +LL | #[repr(packed)] + | ^^^^^^ +LL | #[repr(u32)] +LL | / enum E { +LL | | A, +LL | | B, +LL | | C, +LL | | } + | |_- not a struct or union + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/thaw-validate-invalid-enum.rs:14:9 + | +LL | e: E, + | ^^^^ + | + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` + | +LL | e: std::mem::ManuallyDrop, + | +++++++++++++++++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0517, E0740. +For more information about an error, try `rustc --explain E0517`.