diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ab606478c5136..17be0bd0ab9e1 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -105,21 +105,27 @@ fn map_error<'tcx>( // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); if !field.ty.is_sized(cx.tcx(), cx.typing_env) { - cx.tcx().dcx().delayed_bug(format!( + let guar = cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); + LayoutError::ReferencesError(guar) + } else { + LayoutError::Unknown(ty) } - LayoutError::Unknown(ty) } LayoutCalculatorError::EmptyUnion => { // This is always a compile error. - cx.tcx().dcx().delayed_bug(format!("computed layout of empty union: {ty:?}")); - LayoutError::Unknown(ty) + let guar = + cx.tcx().dcx().delayed_bug(format!("computed layout of empty union: {ty:?}")); + LayoutError::ReferencesError(guar) } 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) + let guar = cx + .tcx() + .dcx() + .delayed_bug(format!("computed impossible repr (packed enum?): {ty:?}")); + LayoutError::ReferencesError(guar) } }; error(cx, err) @@ -432,8 +438,10 @@ fn layout_of_uncached<'tcx>( ty::Adt(def, args) if def.repr().simd() => { if !def.is_struct() { // Should have yielded E0517 by now. - tcx.dcx().delayed_bug("#[repr(simd)] was applied to an ADT that is not a struct"); - return Err(error(cx, LayoutError::Unknown(ty))); + let guar = tcx + .dcx() + .delayed_bug("#[repr(simd)] was applied to an ADT that is not a struct"); + return Err(error(cx, LayoutError::ReferencesError(guar))); } let fields = &def.non_enum_variant().fields; @@ -459,10 +467,10 @@ fn layout_of_uncached<'tcx>( // (should be caught by typeck) for fi in fields { if fi.ty(tcx, args) != f0_ty { - tcx.dcx().delayed_bug( + let guar = tcx.dcx().delayed_bug( "#[repr(simd)] was applied to an ADT with heterogeneous field type", ); - return Err(error(cx, LayoutError::Unknown(ty))); + return Err(error(cx, LayoutError::ReferencesError(guar))); } } @@ -567,11 +575,11 @@ fn layout_of_uncached<'tcx>( if def.is_union() { if def.repr().pack.is_some() && def.repr().align.is_some() { - tcx.dcx().span_delayed_bug( + let guar = tcx.dcx().span_delayed_bug( tcx.def_span(def.did()), "union cannot be packed and aligned", ); - return Err(error(cx, LayoutError::Unknown(ty))); + return Err(error(cx, LayoutError::ReferencesError(guar))); } return Ok(tcx.mk_layout( diff --git a/tests/ui/enum-discriminant/eval-error.rs b/tests/ui/enum-discriminant/eval-error.rs new file mode 100644 index 0000000000000..f2c3b58162765 --- /dev/null +++ b/tests/ui/enum-discriminant/eval-error.rs @@ -0,0 +1,37 @@ +union Foo { + a: str, + //~^ ERROR the size for values of type `str` cannot be known at compilation time + //~| ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` +} + +enum Bar { + Boo = { + let _: Option = None; + 0 + }, +} + +union Foo2 {} +//~^ ERROR unions cannot have zero fields + +enum Bar2 { + Boo = { + let _: Option = None; + 0 + }, +} + +#[repr(u8, packed)] +//~^ ERROR attribute should be applied to a struct or union +enum Foo3 { + A +} + +enum Bar3 { + Boo = { + let _: Option = None; + 0 + }, +} + +fn main() {} diff --git a/tests/ui/enum-discriminant/eval-error.stderr b/tests/ui/enum-discriminant/eval-error.stderr new file mode 100644 index 0000000000000..0f12308de3c1c --- /dev/null +++ b/tests/ui/enum-discriminant/eval-error.stderr @@ -0,0 +1,51 @@ +error: unions cannot have zero fields + --> $DIR/eval-error.rs:14:1 + | +LL | union Foo2 {} + | ^^^^^^^^^^^^^ + +error[E0517]: attribute should be applied to a struct or union + --> $DIR/eval-error.rs:24:12 + | +LL | #[repr(u8, packed)] + | ^^^^^^ +LL | +LL | / enum Foo3 { +LL | | A +LL | | } + | |_- not a struct or union + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/eval-error.rs:2:8 + | +LL | a: str, + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: no field of a union may have a dynamically sized type + = help: change the field's type to have a statically known size +help: borrowed types always have a statically known size + | +LL | a: &str, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | a: Box, + | ++++ + + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/eval-error.rs:2:5 + | +LL | a: str, + | ^^^^^^ + | + = 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 4 previous errors + +Some errors have detailed explanations: E0277, E0517, E0740. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.rs b/tests/ui/layout/base-layout-is-sized-ice-123078.rs index b1c33e1507551..15f11145f845e 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.rs +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.rs @@ -8,7 +8,6 @@ struct S { } const C: S = unsafe { std::mem::transmute(()) }; -//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types const _: [(); { C; 0 diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr index 455bd2cbf8b6e..9181368533a46 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr @@ -16,16 +16,6 @@ help: the `Box` type always has a statically known size and allocates its conten LL | a: Box<[u8]>, | ++++ + -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/base-layout-is-sized-ice-123078.rs:10:23 - | -LL | const C: S = unsafe { std::mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `()` (0 bits) - = note: target type: `S` (size can vary because of [u8]) - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0512. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 1fc55511384f2..319c0de26a90e 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -590,7 +590,7 @@ LL | type Impossible = (str, str); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: the type `EmptyUnion` has an unknown layout +error: the type has an unknown layout --> $DIR/debug.rs:83:1 | LL | union EmptyUnion {}