Skip to content

Commit ea188e9

Browse files
committed
Permit zero non-zero-field on transparent types
1 parent fb3ea63 commit ea188e9

File tree

4 files changed

+46
-76
lines changed

4 files changed

+46
-76
lines changed

compiler/rustc_typeck/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: &'tcx ty
13821382
let non_zst_fields =
13831383
field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None });
13841384
let non_zst_count = non_zst_fields.clone().count();
1385-
if non_zst_count != 1 {
1385+
if non_zst_count >= 2 {
13861386
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
13871387
}
13881388
for (span, zst, align1) in field_infos {

compiler/rustc_typeck/src/check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
10291029
}
10301030
}
10311031

1032-
/// Emit an error when encountering more or less than one variant in a transparent enum.
1032+
/// Emit an error when encountering two or more variants in a transparent enum.
10331033
fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
10341034
let variant_spans: Vec<_> = adt
10351035
.variants
@@ -1048,7 +1048,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d
10481048
err.emit();
10491049
}
10501050

1051-
/// Emit an error when encountering more or less than one non-zero-sized field in a transparent
1051+
/// Emit an error when encountering two or more non-zero-sized fields in a transparent
10521052
/// enum.
10531053
fn bad_non_zero_sized_fields<'tcx>(
10541054
tcx: TyCtxt<'tcx>,
@@ -1057,7 +1057,7 @@ fn bad_non_zero_sized_fields<'tcx>(
10571057
field_spans: impl Iterator<Item = Span>,
10581058
sp: Span,
10591059
) {
1060-
let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count);
1060+
let msg = format!("needs at most one non-zero-sized field, but has {}", field_count);
10611061
let mut err = struct_span_err!(
10621062
tcx.sess,
10631063
sp,

src/test/ui/repr/repr-transparent.rs

+19-13
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,29 @@
88
use std::marker::PhantomData;
99

1010
#[repr(transparent)]
11-
struct NoFields; //~ ERROR needs exactly one non-zero-sized field
11+
struct NoFields;
1212

1313
#[repr(transparent)]
14-
struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field
14+
struct ContainsOnlyZst(());
1515

1616
#[repr(transparent)]
17-
struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field
17+
struct ContainsOnlyZstArray([bool; 0]);
1818

1919
#[repr(transparent)]
2020
struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
21-
//~^ ERROR needs exactly one non-zero-sized field
2221

2322
#[repr(transparent)]
24-
struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field
23+
struct ContainsZstAndNonZst((), [i32; 2]);
24+
25+
#[repr(transparent)]
26+
struct MultipleNonZst(u8, u8); //~ ERROR needs at most one non-zero-sized field
2527

2628
trait Mirror { type It: ?Sized; }
2729
impl<T: ?Sized> Mirror for T { type It = Self; }
2830

2931
#[repr(transparent)]
3032
pub struct StructWithProjection(f32, <f32 as Mirror>::It);
31-
//~^ ERROR needs exactly one non-zero-sized field
33+
//~^ ERROR needs at most one non-zero-sized field
3234

3335
#[repr(transparent)]
3436
struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
@@ -40,22 +42,26 @@ struct ZstAlign32<T>(PhantomData<T>);
4042
struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
4143

4244
#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
43-
enum Void {}
44-
//~^ ERROR transparent enum needs exactly one variant, but has 0
45+
enum Void {} //~ ERROR transparent enum needs exactly one variant, but has 0
4546

4647
#[repr(transparent)]
47-
enum FieldlessEnum { //~ ERROR transparent enum needs exactly one non-zero-sized field, but has 0
48+
enum FieldlessEnum {
4849
Foo,
4950
}
5051

52+
#[repr(transparent)]
53+
enum UnitFieldEnum {
54+
Foo(()),
55+
}
56+
5157
#[repr(transparent)]
5258
enum TooManyFieldsEnum {
5359
Foo(u32, String),
5460
}
55-
//~^^^ ERROR transparent enum needs exactly one non-zero-sized field, but has 2
61+
//~^^^ ERROR transparent enum needs at most one non-zero-sized field, but has 2
5662

5763
#[repr(transparent)]
58-
enum TooManyVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
64+
enum MultipleVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
5965
Foo(String),
6066
Bar,
6167
}
@@ -71,12 +77,12 @@ enum GenericAlignEnum<T> {
7177
}
7278

7379
#[repr(transparent)]
74-
union UnitUnion { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 0
80+
union UnitUnion {
7581
u: (),
7682
}
7783

7884
#[repr(transparent)]
79-
union TooManyFields { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 2
85+
union TooManyFields { //~ ERROR transparent union needs at most one non-zero-sized field, but has 2
8086
u: u32,
8187
s: i32
8288
}
+23-59
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,92 @@
1-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
2-
--> $DIR/repr-transparent.rs:11:1
3-
|
4-
LL | struct NoFields;
5-
| ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
6-
7-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
8-
--> $DIR/repr-transparent.rs:14:1
9-
|
10-
LL | struct ContainsOnlyZst(());
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
12-
13-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
14-
--> $DIR/repr-transparent.rs:17:1
15-
|
16-
LL | struct ContainsOnlyZstArray([bool; 0]);
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
18-
19-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
20-
--> $DIR/repr-transparent.rs:20:1
21-
|
22-
LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
24-
25-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
26-
--> $DIR/repr-transparent.rs:24:1
1+
error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
2+
--> $DIR/repr-transparent.rs:26:1
273
|
284
LL | struct MultipleNonZst(u8, u8);
295
| ^^^^^^^^^^^^^^^^^^^^^^--^^--^^
306
| | | |
317
| | | this field is non-zero-sized
328
| | this field is non-zero-sized
33-
| needs exactly one non-zero-sized field, but has 2
9+
| needs at most one non-zero-sized field, but has 2
3410

35-
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
36-
--> $DIR/repr-transparent.rs:30:1
11+
error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
12+
--> $DIR/repr-transparent.rs:32:1
3713
|
3814
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
3915
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^
4016
| | | |
4117
| | | this field is non-zero-sized
4218
| | this field is non-zero-sized
43-
| needs exactly one non-zero-sized field, but has 2
19+
| needs at most one non-zero-sized field, but has 2
4420

4521
error[E0691]: zero-sized field in transparent struct has alignment larger than 1
46-
--> $DIR/repr-transparent.rs:34:32
22+
--> $DIR/repr-transparent.rs:36:32
4723
|
4824
LL | struct NontrivialAlignZst(u32, [u16; 0]);
4925
| ^^^^^^^^ has alignment larger than 1
5026

5127
error[E0691]: zero-sized field in transparent struct has alignment larger than 1
52-
--> $DIR/repr-transparent.rs:40:24
28+
--> $DIR/repr-transparent.rs:42:24
5329
|
5430
LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
5531
| ^^^^^^^^^^^^^ has alignment larger than 1
5632

5733
error[E0084]: unsupported representation for zero-variant enum
58-
--> $DIR/repr-transparent.rs:42:1
34+
--> $DIR/repr-transparent.rs:44:1
5935
|
6036
LL | #[repr(transparent)]
6137
| ^^^^^^^^^^^^^^^^^^^^
6238
LL | enum Void {}
6339
| ------------ zero-variant enum
6440

6541
error[E0731]: transparent enum needs exactly one variant, but has 0
66-
--> $DIR/repr-transparent.rs:43:1
42+
--> $DIR/repr-transparent.rs:45:1
6743
|
6844
LL | enum Void {}
6945
| ^^^^^^^^^ needs exactly one variant, but has 0
7046

71-
error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0
72-
--> $DIR/repr-transparent.rs:47:1
73-
|
74-
LL | enum FieldlessEnum {
75-
| ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
76-
77-
error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2
78-
--> $DIR/repr-transparent.rs:52:1
47+
error[E0690]: the variant of a transparent enum needs at most one non-zero-sized field, but has 2
48+
--> $DIR/repr-transparent.rs:58:1
7949
|
8050
LL | enum TooManyFieldsEnum {
81-
| ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
51+
| ^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
8252
LL | Foo(u32, String),
8353
| --- ------ this field is non-zero-sized
8454
| |
8555
| this field is non-zero-sized
8656

8757
error[E0731]: transparent enum needs exactly one variant, but has 2
88-
--> $DIR/repr-transparent.rs:58:1
58+
--> $DIR/repr-transparent.rs:64:1
8959
|
90-
LL | enum TooManyVariants {
91-
| ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
60+
LL | enum MultipleVariants {
61+
| ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
9262
LL | Foo(String),
9363
| -----------
9464
LL | Bar,
95-
| --- too many variants in `TooManyVariants`
65+
| --- too many variants in `MultipleVariants`
9666

9767
error[E0691]: zero-sized field in transparent enum has alignment larger than 1
98-
--> $DIR/repr-transparent.rs:65:14
68+
--> $DIR/repr-transparent.rs:71:14
9969
|
10070
LL | Foo(u32, [u16; 0]),
10171
| ^^^^^^^^ has alignment larger than 1
10272

10373
error[E0691]: zero-sized field in transparent enum has alignment larger than 1
104-
--> $DIR/repr-transparent.rs:70:11
74+
--> $DIR/repr-transparent.rs:76:11
10575
|
10676
LL | Foo { bar: ZstAlign32<T>, baz: u32 }
10777
| ^^^^^^^^^^^^^^^^^^ has alignment larger than 1
10878

109-
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0
110-
--> $DIR/repr-transparent.rs:74:1
111-
|
112-
LL | union UnitUnion {
113-
| ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
114-
115-
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2
116-
--> $DIR/repr-transparent.rs:79:1
79+
error[E0690]: transparent union needs at most one non-zero-sized field, but has 2
80+
--> $DIR/repr-transparent.rs:85:1
11781
|
11882
LL | union TooManyFields {
119-
| ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2
83+
| ^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
12084
LL | u: u32,
12185
| ------ this field is non-zero-sized
12286
LL | s: i32
12387
| ------ this field is non-zero-sized
12488

125-
error: aborting due to 17 previous errors
89+
error: aborting due to 11 previous errors
12690

12791
Some errors have detailed explanations: E0084, E0690, E0691, E0731.
12892
For more information about an error, try `rustc --explain E0084`.

0 commit comments

Comments
 (0)