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 afdfa2e80c1f6..38b292afe8d71 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -30,7 +30,8 @@ use {rustc_abi as abi, rustc_hir as hir}; use crate::errors::{ MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, }; -use crate::layout_sanity_check::sanity_check_layout; + +mod invariant; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { layout_of, ..*providers }; @@ -79,7 +80,7 @@ fn layout_of<'tcx>( record_layout_for_printing(&cx, layout); } - sanity_check_layout(&cx, &layout); + invariant::partially_check_layout(&cx, &layout); Ok(layout) } @@ -115,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/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs similarity index 99% rename from compiler/rustc_ty_utils/src/layout_sanity_check.rs rename to compiler/rustc_ty_utils/src/layout/invariant.rs index be0a7c5ee890a..6cf114b74c13d 100644 --- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; use rustc_target::abi::*; /// Enforce some basic invariants on layouts. -pub(super) fn sanity_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { +pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { let tcx = cx.tcx(); // Type-level uninhabitedness should always imply ABI uninhabitedness. diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index dc5303317a8a0..8be1611bb9ac2 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -29,7 +29,6 @@ mod errors; mod implied_bounds; mod instance; mod layout; -mod layout_sanity_check; mod needs_drop; mod opaque_types; mod representability; diff --git a/tests/crashes/126966.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs similarity index 50% rename from tests/crashes/126966.rs rename to tests/ui/layout/thaw-transmute-invalid-enum.rs index 2c9f1a70f4fbf..835dcc049964f 100644 --- a/tests/crashes/126966.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/crashes/128870.rs b/tests/ui/layout/thaw-validate-invalid-enum.rs similarity index 61% rename from tests/crashes/128870.rs rename to tests/ui/layout/thaw-validate-invalid-enum.rs index 2b7319621440c..51aff7fb556c2 100644 --- a/tests/crashes/128870.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`.