diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index bbdda155496fa..41679e3a68e56 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1366,7 +1366,7 @@ impl<'a> DiagCtxtHandle<'a> { self.create_err(err).emit() } - /// Ensures that an error is printed. See `Level::DelayedBug`. + /// Ensures that an error is printed. See [`Level::DelayedBug`]. // // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't // user-facing. diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index d1484aed16718..01435f7e67a46 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -281,10 +281,16 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou } // Ensure that for niche encoded tags the discriminant coincides with the variant index. - assert_eq!( - layout.ty.discriminant_for_variant(tcx, idx).unwrap().val, - u128::from(idx.as_u32()), - ); + let val = layout.ty.discriminant_for_variant(tcx, idx).unwrap().val; + if val != u128::from(idx.as_u32()) { + let adt_def = layout.ty.ty_adt_def().unwrap(); + cx.tcx().dcx().span_delayed_bug( + cx.tcx().def_span(adt_def.did()), + format!( + "variant {idx:?} has discriminant {val:?} in niche-encoded type" + ), + ); + } } } for variant in variants.iter() { diff --git a/tests/ui/enum-discriminant/invalid-niche-discriminant.normal.stderr b/tests/ui/enum-discriminant/invalid-niche-discriminant.normal.stderr new file mode 100644 index 0000000000000..9c66c1782e4dc --- /dev/null +++ b/tests/ui/enum-discriminant/invalid-niche-discriminant.normal.stderr @@ -0,0 +1,35 @@ +error[E0732]: `#[repr(inttype)]` must be specified for enums with explicit discriminants and non-unit variants + --> $DIR/invalid-niche-discriminant.rs:11:1 + | +LL | enum E { + | ^^^^^^ +... +LL | S0 { + | -- non-unit discriminant declared here +... +LL | Bar = { + | ___________- +LL | | let x = 1; +LL | | 3 +LL | | }, + | |_____- explicit discriminant specified here + +error[E0599]: no variant named `S1` found for enum `E` + --> $DIR/invalid-niche-discriminant.rs:23:18 + | +LL | enum E { + | ------ variant `S1` not found here +... +LL | static C: E = E::S1 { u: 23 }; + | ^^ + | +help: there is a variant with a similar name + | +LL - static C: E = E::S1 { u: 23 }; +LL + static C: E = E::S0 { u: 23 }; + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0732. +For more information about an error, try `rustc --explain E0599`. diff --git a/tests/ui/enum-discriminant/invalid-niche-discriminant.rs b/tests/ui/enum-discriminant/invalid-niche-discriminant.rs new file mode 100644 index 0000000000000..f70f7d1736bae --- /dev/null +++ b/tests/ui/enum-discriminant/invalid-niche-discriminant.rs @@ -0,0 +1,25 @@ +//@ needs-rustc-debug-assertions +//@ revisions: normal with_delayed +//@ [with_delayed] compile-flags: -Z eagerly-emit-delayed-bugs + +#![crate_type = "lib"] + +// Repro for +// which ICEd because the calculated layout is invalid +// but which we needn't care about as the discriminant already was. + +enum E { +//~^ ERROR must be specified +//[with_delayed]~| ERROR variant 1 has discriminant 3 + S0 { + s: String, + }, + Bar = { + let x = 1; + 3 + }, +} + +static C: E = E::S1 { u: 23 }; +//~^ ERROR no variant named +//[with_delayed]~| ERROR but no error emitted diff --git a/tests/ui/enum-discriminant/invalid-niche-discriminant.with_delayed.stderr b/tests/ui/enum-discriminant/invalid-niche-discriminant.with_delayed.stderr new file mode 100644 index 0000000000000..20f118655a17a --- /dev/null +++ b/tests/ui/enum-discriminant/invalid-niche-discriminant.with_delayed.stderr @@ -0,0 +1,47 @@ +error[E0732]: `#[repr(inttype)]` must be specified for enums with explicit discriminants and non-unit variants + --> $DIR/invalid-niche-discriminant.rs:11:1 + | +LL | enum E { + | ^^^^^^ +... +LL | S0 { + | -- non-unit discriminant declared here +... +LL | Bar = { + | ___________- +LL | | let x = 1; +LL | | 3 +LL | | }, + | |_____- explicit discriminant specified here + +error: variant 1 has discriminant 3 in niche-encoded type + --> $DIR/invalid-niche-discriminant.rs:11:1 + | +LL | enum E { + | ^^^^^^ + +error[E0599]: no variant named `S1` found for enum `E` + --> $DIR/invalid-niche-discriminant.rs:23:18 + | +LL | enum E { + | ------ variant `S1` not found here +... +LL | static C: E = E::S1 { u: 23 }; + | ^^ + | +help: there is a variant with a similar name + | +LL - static C: E = E::S1 { u: 23 }; +LL + static C: E = E::S0 { u: 23 }; + | + +error: `Res::Err` but no error emitted + --> $DIR/invalid-niche-discriminant.rs:23:15 + | +LL | static C: E = E::S1 { u: 23 }; + | ^^^^^ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0599, E0732. +For more information about an error, try `rustc --explain E0599`.