Skip to content

Commit 9f4c915

Browse files
compiler: Reject impossible reprs during enum layout
1 parent 68d1fd9 commit 9f4c915

File tree

6 files changed

+121
-4
lines changed

6 files changed

+121
-4
lines changed

Diff for: compiler/rustc_abi/src/layout.rs

+9
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pub enum LayoutCalculatorError<F> {
5454

5555
/// A union had no fields.
5656
EmptyUnion,
57+
58+
/// The fields or variants have irreconcilable reprs
59+
ReprConflict,
5760
}
5861

5962
impl<F> LayoutCalculatorError<F> {
@@ -64,6 +67,7 @@ impl<F> LayoutCalculatorError<F> {
6467
}
6568
LayoutCalculatorError::SizeOverflow => LayoutCalculatorError::SizeOverflow,
6669
LayoutCalculatorError::EmptyUnion => LayoutCalculatorError::EmptyUnion,
70+
LayoutCalculatorError::ReprConflict => LayoutCalculatorError::ReprConflict,
6771
}
6872
}
6973

@@ -77,6 +81,7 @@ impl<F> LayoutCalculatorError<F> {
7781
}
7882
LayoutCalculatorError::SizeOverflow => "size overflow",
7983
LayoutCalculatorError::EmptyUnion => "type is a union with no fields",
84+
LayoutCalculatorError::ReprConflict => "type has an invalid repr",
8085
})
8186
}
8287
}
@@ -514,6 +519,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
514519
}
515520

516521
let dl = self.cx.data_layout();
522+
// bail if the enum has an incoherent repr that cannot be computed
523+
if repr.packed() {
524+
return Err(LayoutCalculatorError::ReprConflict);
525+
}
517526

518527
let calculate_niche_filling_layout = || -> Option<TmpLayout<FieldIdx, VariantIdx>> {
519528
if dont_niche_optimize_enum {

Diff for: compiler/rustc_ty_utils/src/layout.rs

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ fn map_error<'tcx>(
116116
cx.tcx().dcx().delayed_bug(format!("computed layout of empty union: {ty:?}"));
117117
LayoutError::Unknown(ty)
118118
}
119+
LayoutCalculatorError::ReprConflict => {
120+
// packed enums are the only known trigger of this, but others might arise
121+
cx.tcx().dcx().delayed_bug(format!("computed impossible repr (packed enum?): {ty:?}"));
122+
LayoutError::Unknown(ty)
123+
}
119124
};
120125
error(cx, err)
121126
}

Diff for: tests/ui/layout/thaw-transmute-invalid-enum.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
//@ known-bug: rust-lang/rust#126966
1+
#![crate_type = "lib"]
2+
23
mod assert {
34
use std::mem::{Assume, TransmuteFrom};
5+
//~^ ERROR: use of unstable library feature 'transmutability'
6+
//~| ERROR: use of unstable library feature 'transmutability'
47

58
pub fn is_transmutable<Src, Dst>()
69
where
710
Dst: TransmuteFrom<Src>,
11+
//~^ ERROR: use of unstable library feature 'transmutability'
812
{
913
}
1014
}
@@ -15,15 +19,18 @@ enum Ox00 {
1519
}
1620

1721
#[repr(C, packed(2))]
22+
//~^ ERROR: attribute should be applied to a struct
1823
enum OxFF {
1924
V = 0xFF,
2025
}
2126

2227
fn test() {
2328
union Superset {
2429
a: Ox00,
30+
//~^ ERROR: field must implement `Copy`
2531
b: OxFF,
2632
}
2733

2834
assert::is_transmutable::<Superset, Subset>();
35+
//~^ ERROR: cannot find type `Subset`
2936
}

Diff for: tests/ui/layout/thaw-transmute-invalid-enum.stderr

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
error[E0412]: cannot find type `Subset` in this scope
2+
--> $DIR/thaw-transmute-invalid-enum.rs:34:41
3+
|
4+
LL | assert::is_transmutable::<Superset, Subset>();
5+
| ^^^^^^ not found in this scope
6+
|
7+
help: you might be missing a type parameter
8+
|
9+
LL | fn test<Subset>() {
10+
| ++++++++
11+
12+
error[E0517]: attribute should be applied to a struct or union
13+
--> $DIR/thaw-transmute-invalid-enum.rs:21:11
14+
|
15+
LL | #[repr(C, packed(2))]
16+
| ^^^^^^^^^
17+
LL |
18+
LL | / enum OxFF {
19+
LL | | V = 0xFF,
20+
LL | | }
21+
| |_- not a struct or union
22+
23+
error[E0658]: use of unstable library feature 'transmutability'
24+
--> $DIR/thaw-transmute-invalid-enum.rs:4:20
25+
|
26+
LL | use std::mem::{Assume, TransmuteFrom};
27+
| ^^^^^^
28+
|
29+
= note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
30+
= help: add `#![feature(transmutability)]` to the crate attributes to enable
31+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
32+
33+
error[E0658]: use of unstable library feature 'transmutability'
34+
--> $DIR/thaw-transmute-invalid-enum.rs:4:28
35+
|
36+
LL | use std::mem::{Assume, TransmuteFrom};
37+
| ^^^^^^^^^^^^^
38+
|
39+
= note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
40+
= help: add `#![feature(transmutability)]` to the crate attributes to enable
41+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
42+
43+
error[E0658]: use of unstable library feature 'transmutability'
44+
--> $DIR/thaw-transmute-invalid-enum.rs:10:14
45+
|
46+
LL | Dst: TransmuteFrom<Src>,
47+
| ^^^^^^^^^^^^^^^^^^
48+
|
49+
= note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information
50+
= help: add `#![feature(transmutability)]` to the crate attributes to enable
51+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
52+
53+
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
54+
--> $DIR/thaw-transmute-invalid-enum.rs:29:9
55+
|
56+
LL | a: Ox00,
57+
| ^^^^^^^
58+
|
59+
= note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
60+
help: wrap the field type in `ManuallyDrop<...>`
61+
|
62+
LL | a: std::mem::ManuallyDrop<Ox00>,
63+
| +++++++++++++++++++++++ +
64+
65+
error: aborting due to 6 previous errors
66+
67+
Some errors have detailed explanations: E0412, E0517, E0658, E0740.
68+
For more information about an error, try `rustc --explain E0412`.

Diff for: tests/ui/layout/thaw-validate-invalid-enum.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
//@ known-bug: rust-lang/rust#128870
21
//@ compile-flags: -Zvalidate-mir
32

4-
#[repr(packed)]
3+
#[repr(packed)] //~ ERROR: attribute should be applied to a struct
54
#[repr(u32)]
65
enum E {
76
A,
@@ -12,7 +11,7 @@ enum E {
1211
fn main() {
1312
union InvalidTag {
1413
int: u32,
15-
e: E,
14+
e: E, //~ ERROR: field must implement `Copy`
1615
}
1716
let _invalid_tag = InvalidTag { int: 4 };
1817
}

Diff for: tests/ui/layout/thaw-validate-invalid-enum.stderr

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0517]: attribute should be applied to a struct or union
2+
--> $DIR/thaw-validate-invalid-enum.rs:3:8
3+
|
4+
LL | #[repr(packed)]
5+
| ^^^^^^
6+
LL | #[repr(u32)]
7+
LL | / enum E {
8+
LL | | A,
9+
LL | | B,
10+
LL | | C,
11+
LL | | }
12+
| |_- not a struct or union
13+
14+
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
15+
--> $DIR/thaw-validate-invalid-enum.rs:14:9
16+
|
17+
LL | e: E,
18+
| ^^^^
19+
|
20+
= note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
21+
help: wrap the field type in `ManuallyDrop<...>`
22+
|
23+
LL | e: std::mem::ManuallyDrop<E>,
24+
| +++++++++++++++++++++++ +
25+
26+
error: aborting due to 2 previous errors
27+
28+
Some errors have detailed explanations: E0517, E0740.
29+
For more information about an error, try `rustc --explain E0517`.

0 commit comments

Comments
 (0)