Skip to content

Commit 4d38062

Browse files
Rollup merge of #145791 - samueltardieu:fix-zst-to-enum-mir-validation, r=compiler-errors
Fix ICE when validating transmuting ZST to inhabited enum MIR validation attempts to determine the number of bytes needed to represent the size of the source type to compute the discriminant for the inhabited target enum. For a ZST source, there is no source data to use as a discriminant so no proper runtime check can be generated. Since that should never be possible, insert a delayed bug to ensure the problem has been properly reported to the user by the type checker. Fixes #145786
2 parents a1cdd14 + 323e230 commit 4d38062

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

compiler/rustc_mir_transform/src/check_enums.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ impl<'tcx> crate::MirPass<'tcx> for CheckEnums {
4848
let new_block = split_block(basic_blocks, location);
4949

5050
match check {
51+
EnumCheckType::Direct { op_size, .. }
52+
| EnumCheckType::WithNiche { op_size, .. }
53+
if op_size.bytes() == 0 =>
54+
{
55+
// It is never valid to use a ZST as a discriminant for an inhabited enum, but that will
56+
// have been caught by the type checker. Do nothing but ensure that a bug has been signaled.
57+
tcx.dcx().span_delayed_bug(
58+
source_info.span,
59+
"cannot build enum discriminant from zero-sized type",
60+
);
61+
basic_blocks[block].terminator = Some(Terminator {
62+
source_info,
63+
kind: TerminatorKind::Goto { target: new_block },
64+
});
65+
}
5166
EnumCheckType::Direct { source_op, discr, op_size, valid_discrs } => {
5267
insert_direct_enum_check(
5368
tcx,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Do not attempt to take the discriminant as the source
2+
// converted to a `u128`, that won't work for ZST.
3+
//
4+
//@ compile-flags: -Zvalidate-mir
5+
6+
enum A {
7+
B,
8+
C,
9+
}
10+
11+
fn main() {
12+
let _: A = unsafe { std::mem::transmute(()) };
13+
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
2+
--> $DIR/ice-zst-as-discr-145786.rs:12:25
3+
|
4+
LL | let _: A = unsafe { std::mem::transmute(()) };
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: source type: `()` (0 bits)
8+
= note: target type: `A` (8 bits)
9+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0512`.

0 commit comments

Comments
 (0)