Permit zero non-zero-field on transparent types

This commit is contained in:
Yuki Okushi 2021-06-14 07:04:56 +09:00
parent fb3ea63d9b
commit ea188e9d21
No known key found for this signature in database
GPG Key ID: DABA5B072961C18A
4 changed files with 46 additions and 76 deletions

View File

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

View File

@ -1029,7 +1029,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
} }
} }
/// Emit an error when encountering more or less than one variant in a transparent enum. /// Emit an error when encountering two or more variants in a transparent enum.
fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) { fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
let variant_spans: Vec<_> = adt let variant_spans: Vec<_> = adt
.variants .variants
@ -1048,7 +1048,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d
err.emit(); err.emit();
} }
/// Emit an error when encountering more or less than one non-zero-sized field in a transparent /// Emit an error when encountering two or more non-zero-sized fields in a transparent
/// enum. /// enum.
fn bad_non_zero_sized_fields<'tcx>( fn bad_non_zero_sized_fields<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
@ -1057,7 +1057,7 @@ fn bad_non_zero_sized_fields<'tcx>(
field_spans: impl Iterator<Item = Span>, field_spans: impl Iterator<Item = Span>,
sp: Span, sp: Span,
) { ) {
let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count); let msg = format!("needs at most one non-zero-sized field, but has {}", field_count);
let mut err = struct_span_err!( let mut err = struct_span_err!(
tcx.sess, tcx.sess,
sp, sp,

View File

@ -8,27 +8,29 @@
use std::marker::PhantomData; use std::marker::PhantomData;
#[repr(transparent)] #[repr(transparent)]
struct NoFields; //~ ERROR needs exactly one non-zero-sized field struct NoFields;
#[repr(transparent)] #[repr(transparent)]
struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field struct ContainsOnlyZst(());
#[repr(transparent)] #[repr(transparent)]
struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field struct ContainsOnlyZstArray([bool; 0]);
#[repr(transparent)] #[repr(transparent)]
struct ContainsMultipleZst(PhantomData<*const i32>, NoFields); struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
//~^ ERROR needs exactly one non-zero-sized field
#[repr(transparent)] #[repr(transparent)]
struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field struct ContainsZstAndNonZst((), [i32; 2]);
#[repr(transparent)]
struct MultipleNonZst(u8, u8); //~ ERROR needs at most one non-zero-sized field
trait Mirror { type It: ?Sized; } trait Mirror { type It: ?Sized; }
impl<T: ?Sized> Mirror for T { type It = Self; } impl<T: ?Sized> Mirror for T { type It = Self; }
#[repr(transparent)] #[repr(transparent)]
pub struct StructWithProjection(f32, <f32 as Mirror>::It); pub struct StructWithProjection(f32, <f32 as Mirror>::It);
//~^ ERROR needs exactly one non-zero-sized field //~^ ERROR needs at most one non-zero-sized field
#[repr(transparent)] #[repr(transparent)]
struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1 struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
@ -40,22 +42,26 @@ struct ZstAlign32<T>(PhantomData<T>);
struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1 struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum #[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
enum Void {} enum Void {} //~ ERROR transparent enum needs exactly one variant, but has 0
//~^ ERROR transparent enum needs exactly one variant, but has 0
#[repr(transparent)] #[repr(transparent)]
enum FieldlessEnum { //~ ERROR transparent enum needs exactly one non-zero-sized field, but has 0 enum FieldlessEnum {
Foo, Foo,
} }
#[repr(transparent)]
enum UnitFieldEnum {
Foo(()),
}
#[repr(transparent)] #[repr(transparent)]
enum TooManyFieldsEnum { enum TooManyFieldsEnum {
Foo(u32, String), Foo(u32, String),
} }
//~^^^ ERROR transparent enum needs exactly one non-zero-sized field, but has 2 //~^^^ ERROR transparent enum needs at most one non-zero-sized field, but has 2
#[repr(transparent)] #[repr(transparent)]
enum TooManyVariants { //~ ERROR transparent enum needs exactly one variant, but has 2 enum MultipleVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
Foo(String), Foo(String),
Bar, Bar,
} }
@ -71,12 +77,12 @@ enum GenericAlignEnum<T> {
} }
#[repr(transparent)] #[repr(transparent)]
union UnitUnion { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 0 union UnitUnion {
u: (), u: (),
} }
#[repr(transparent)] #[repr(transparent)]
union TooManyFields { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 2 union TooManyFields { //~ ERROR transparent union needs at most one non-zero-sized field, but has 2
u: u32, u: u32,
s: i32 s: i32
} }

View File

@ -1,61 +1,37 @@
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:11:1 --> $DIR/repr-transparent.rs:26:1
|
LL | struct NoFields;
| ^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:14:1
|
LL | struct ContainsOnlyZst(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:17:1
|
LL | struct ContainsOnlyZstArray([bool; 0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:20:1
|
LL | struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:24:1
| |
LL | struct MultipleNonZst(u8, u8); LL | struct MultipleNonZst(u8, u8);
| ^^^^^^^^^^^^^^^^^^^^^^--^^--^^ | ^^^^^^^^^^^^^^^^^^^^^^--^^--^^
| | | | | | | |
| | | this field is non-zero-sized | | | this field is non-zero-sized
| | this field is non-zero-sized | | this field is non-zero-sized
| needs exactly one non-zero-sized field, but has 2 | needs at most one non-zero-sized field, but has 2
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2 error[E0690]: transparent struct needs at most one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:30:1 --> $DIR/repr-transparent.rs:32:1
| |
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It); LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^-------------------^^
| | | | | | | |
| | | this field is non-zero-sized | | | this field is non-zero-sized
| | this field is non-zero-sized | | this field is non-zero-sized
| needs exactly one non-zero-sized field, but has 2 | needs at most one non-zero-sized field, but has 2
error[E0691]: zero-sized field in transparent struct has alignment larger than 1 error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:34:32 --> $DIR/repr-transparent.rs:36:32
| |
LL | struct NontrivialAlignZst(u32, [u16; 0]); LL | struct NontrivialAlignZst(u32, [u16; 0]);
| ^^^^^^^^ has alignment larger than 1 | ^^^^^^^^ has alignment larger than 1
error[E0691]: zero-sized field in transparent struct has alignment larger than 1 error[E0691]: zero-sized field in transparent struct has alignment larger than 1
--> $DIR/repr-transparent.rs:40:24 --> $DIR/repr-transparent.rs:42:24
| |
LL | struct GenericAlign<T>(ZstAlign32<T>, u32); LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
| ^^^^^^^^^^^^^ has alignment larger than 1 | ^^^^^^^^^^^^^ has alignment larger than 1
error[E0084]: unsupported representation for zero-variant enum error[E0084]: unsupported representation for zero-variant enum
--> $DIR/repr-transparent.rs:42:1 --> $DIR/repr-transparent.rs:44:1
| |
LL | #[repr(transparent)] LL | #[repr(transparent)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
@ -63,66 +39,54 @@ LL | enum Void {}
| ------------ zero-variant enum | ------------ zero-variant enum
error[E0731]: transparent enum needs exactly one variant, but has 0 error[E0731]: transparent enum needs exactly one variant, but has 0
--> $DIR/repr-transparent.rs:43:1 --> $DIR/repr-transparent.rs:45:1
| |
LL | enum Void {} LL | enum Void {}
| ^^^^^^^^^ needs exactly one variant, but has 0 | ^^^^^^^^^ needs exactly one variant, but has 0
error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0 error[E0690]: the variant of a transparent enum needs at most one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:47:1 --> $DIR/repr-transparent.rs:58:1
|
LL | enum FieldlessEnum {
| ^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:52:1
| |
LL | enum TooManyFieldsEnum { LL | enum TooManyFieldsEnum {
| ^^^^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 | ^^^^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
LL | Foo(u32, String), LL | Foo(u32, String),
| --- ------ this field is non-zero-sized | --- ------ this field is non-zero-sized
| | | |
| this field is non-zero-sized | this field is non-zero-sized
error[E0731]: transparent enum needs exactly one variant, but has 2 error[E0731]: transparent enum needs exactly one variant, but has 2
--> $DIR/repr-transparent.rs:58:1 --> $DIR/repr-transparent.rs:64:1
| |
LL | enum TooManyVariants { LL | enum MultipleVariants {
| ^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2
LL | Foo(String), LL | Foo(String),
| ----------- | -----------
LL | Bar, LL | Bar,
| --- too many variants in `TooManyVariants` | --- too many variants in `MultipleVariants`
error[E0691]: zero-sized field in transparent enum has alignment larger than 1 error[E0691]: zero-sized field in transparent enum has alignment larger than 1
--> $DIR/repr-transparent.rs:65:14 --> $DIR/repr-transparent.rs:71:14
| |
LL | Foo(u32, [u16; 0]), LL | Foo(u32, [u16; 0]),
| ^^^^^^^^ has alignment larger than 1 | ^^^^^^^^ has alignment larger than 1
error[E0691]: zero-sized field in transparent enum has alignment larger than 1 error[E0691]: zero-sized field in transparent enum has alignment larger than 1
--> $DIR/repr-transparent.rs:70:11 --> $DIR/repr-transparent.rs:76:11
| |
LL | Foo { bar: ZstAlign32<T>, baz: u32 } LL | Foo { bar: ZstAlign32<T>, baz: u32 }
| ^^^^^^^^^^^^^^^^^^ has alignment larger than 1 | ^^^^^^^^^^^^^^^^^^ has alignment larger than 1
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0 error[E0690]: transparent union needs at most one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:74:1 --> $DIR/repr-transparent.rs:85:1
|
LL | union UnitUnion {
| ^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 0
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:79:1
| |
LL | union TooManyFields { LL | union TooManyFields {
| ^^^^^^^^^^^^^^^^^^^ needs exactly one non-zero-sized field, but has 2 | ^^^^^^^^^^^^^^^^^^^ needs at most one non-zero-sized field, but has 2
LL | u: u32, LL | u: u32,
| ------ this field is non-zero-sized | ------ this field is non-zero-sized
LL | s: i32 LL | s: i32
| ------ this field is non-zero-sized | ------ this field is non-zero-sized
error: aborting due to 17 previous errors error: aborting due to 11 previous errors
Some errors have detailed explanations: E0084, E0690, E0691, E0731. Some errors have detailed explanations: E0084, E0690, E0691, E0731.
For more information about an error, try `rustc --explain E0084`. For more information about an error, try `rustc --explain E0084`.