Auto merge of #60463 - mjbshaw:transparent, r=varkor,rkruppe

Implement RFC 2645 (transparent enums and unions)

Tracking issue: #60405
This commit is contained in:
bors 2019-06-11 11:06:38 +00:00
commit 8e948df707
34 changed files with 730 additions and 208 deletions

View file

@ -0,0 +1,93 @@
# `transparent_enums`
The tracking issue for this feature is [#60405]
[60405]: https://github.com/rust-lang/rust/issues/60405
----
The `transparent_enums` feature allows you mark `enum`s as
`#[repr(transparent)]`. An `enum` may be `#[repr(transparent)]` if it has
exactly one variant, and that variant matches the same conditions which `struct`
requires for transparency. Some concrete illustrations follow.
```rust
#![feature(transparent_enums)]
// This enum has the same representation as `f32`.
#[repr(transparent)]
enum SingleFieldEnum {
Variant(f32)
}
// This enum has the same representation as `usize`.
#[repr(transparent)]
enum MultiFieldEnum {
Variant { field: usize, nothing: () },
}
```
For consistency with transparent `struct`s, `enum`s must have exactly one
non-zero-sized field. If all fields are zero-sized, the `enum` must not be
`#[repr(transparent)]`:
```rust
#![feature(transparent_enums)]
// This (non-transparent) enum is already valid in stable Rust:
pub enum GoodEnum {
Nothing,
}
// Error: transparent enum needs exactly one non-zero-sized field, but has 0
// #[repr(transparent)]
// pub enum BadEnum {
// Nothing(()),
// }
// Error: transparent enum needs exactly one non-zero-sized field, but has 0
// #[repr(transparent)]
// pub enum BadEmptyEnum {
// Nothing,
// }
```
The one exception is if the `enum` is generic over `T` and has a field of type
`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type:
```rust
#![feature(transparent_enums)]
// This enum has the same representation as `T`.
#[repr(transparent)]
pub enum GenericEnum<T> {
Variant(T, ()),
}
// This is okay even though `()` is a zero-sized type.
pub const THIS_IS_OKAY: GenericEnum<()> = GenericEnum::Variant((), ());
```
Transparent `enum`s require exactly one variant:
```rust
// Error: transparent enum needs exactly one variant, but has 0
// #[repr(transparent)]
// pub enum TooFewVariants {
// }
// Error: transparent enum needs exactly one variant, but has 2
// #[repr(transparent)]
// pub enum TooManyVariants {
// First(usize),
// Second,
// }
```
Like transarent `struct`s, a transparent `enum` of type `E` has the same layout,
size, and ABI as its single non-ZST field. If it is generic over a type `T`, and
all its fields are ZSTs except for exactly one field of type `T`, then it has
the same layout and ABI as `T` (even if `T` is a ZST when monomorphized).
Like transparent `struct`s, transparent `enum`s are FFI-safe if and only if
their underlying representation type is also FFI-safe.

View file

@ -0,0 +1,83 @@
# `transparent_unions`
The tracking issue for this feature is [#60405]
[60405]: https://github.com/rust-lang/rust/issues/60405
----
The `transparent_unions` feature allows you mark `union`s as
`#[repr(transparent)]`. A `union` may be `#[repr(transparent)]` in exactly the
same conditions in which a `struct` may be `#[repr(transparent)]` (generally,
this means the `union` must have exactly one non-zero-sized field). Some
concrete illustrations follow.
```rust
#![feature(transparent_unions)]
// This union has the same representation as `f32`.
#[repr(transparent)]
union SingleFieldUnion {
field: f32,
}
// This union has the same representation as `usize`.
#[repr(transparent)]
union MultiFieldUnion {
field: usize,
nothing: (),
}
```
For consistency with transparent `struct`s, `union`s must have exactly one
non-zero-sized field. If all fields are zero-sized, the `union` must not be
`#[repr(transparent)]`:
```rust
#![feature(transparent_unions)]
// This (non-transparent) union is already valid in stable Rust:
pub union GoodUnion {
pub nothing: (),
}
// Error: transparent union needs exactly one non-zero-sized field, but has 0
// #[repr(transparent)]
// pub union BadUnion {
// pub nothing: (),
// }
```
The one exception is if the `union` is generic over `T` and has a field of type
`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type:
```rust
#![feature(transparent_unions)]
// This union has the same representation as `T`.
#[repr(transparent)]
pub union GenericUnion<T: Copy> { // Unions with non-`Copy` fields are unstable.
pub field: T,
pub nothing: (),
}
// This is okay even though `()` is a zero-sized type.
pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () };
```
Like transarent `struct`s, a transparent `union` of type `U` has the same
layout, size, and ABI as its single non-ZST field. If it is generic over a type
`T`, and all its fields are ZSTs except for exactly one field of type `T`, then
it has the same layout and ABI as `T` (even if `T` is a ZST when monomorphized).
Like transparent `struct`s, transparent `union`s are FFI-safe if and only if
their underlying representation type is also FFI-safe.
A `union` may not be eligible for the same nonnull-style optimizations that a
`struct` or `enum` (with the same fields) are eligible for. Adding
`#[repr(transparent)]` to `union` does not change this. To give a more concrete
example, it is unspecified whether `size_of::<T>()` is equal to
`size_of::<Option<T>>()`, where `T` is a `union` (regardless of whether or not
it is transparent). The Rust compiler is free to perform this optimization if
possible, but is not required to, and different compiler versions may differ in
their application of these optimizations.

View file

@ -181,12 +181,9 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
let (article, allowed_targets) = match hint.name_or_empty() {
name @ sym::C | name @ sym::align => {
is_c |= name == sym::C;
if target != Target::Struct &&
target != Target::Union &&
target != Target::Enum {
("a", "struct, enum or union")
} else {
continue
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => ("a", "struct, enum, or union"),
}
}
sym::packed => {
@ -207,10 +204,9 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
}
sym::transparent => {
is_transparent = true;
if target != Target::Struct {
("a", "struct")
} else {
continue
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => ("a", "struct, enum, or union"),
}
}
sym::i8 | sym::u8 | sym::i16 | sym::u16 |
@ -241,7 +237,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
span_err!(self.tcx.sess, hint_spans, E0692,
"transparent struct cannot have other repr hints");
"transparent {} cannot have other repr hints", target);
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
@ -277,7 +273,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
attr.span,
stmt.span,
"attribute should not be applied to a statement",
"not a struct, enum or union",
"not a struct, enum, or union",
);
}
}
@ -298,7 +294,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
attr.span,
expr.span,
"attribute should not be applied to an expression",
"not defining a struct, enum or union",
"not defining a struct, enum, or union",
);
}
}

View file

@ -2303,7 +2303,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
/// Returns an iterator over all fields contained
/// by this ADT.
#[inline]
pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> {
pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> + Clone {
self.variants.iter().flat_map(|v| v.fields.iter())
}

View file

@ -531,8 +531,8 @@ fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> b
match ty.sty {
ty::FnPtr(_) => true,
ty::Ref(..) => true,
ty::Adt(field_def, substs) if field_def.repr.transparent() && field_def.is_struct() => {
for field in &field_def.non_enum_variant().fields {
ty::Adt(field_def, substs) if field_def.repr.transparent() && !field_def.is_union() => {
for field in field_def.all_fields() {
let field_ty = tcx.normalize_erasing_regions(
ParamEnv::reveal_all(),
field.ty(tcx, substs),
@ -627,8 +627,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
return FfiUnsafe {
ty: ty,
reason: "this struct has unspecified layout",
help: Some("consider adding a #[repr(C)] or #[repr(transparent)] \
attribute to this struct"),
help: Some("consider adding a `#[repr(C)]` or \
`#[repr(transparent)]` attribute to this struct"),
};
}
@ -668,11 +668,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if all_phantom { FfiPhantom(ty) } else { FfiSafe }
}
AdtKind::Union => {
if !def.repr.c() {
if !def.repr.c() && !def.repr.transparent() {
return FfiUnsafe {
ty: ty,
reason: "this union has unspecified layout",
help: Some("consider adding a #[repr(C)] attribute to this union"),
help: Some("consider adding a `#[repr(C)]` or \
`#[repr(transparent)]` attribute to this union"),
};
}
@ -690,6 +691,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ParamEnv::reveal_all(),
field.ty(cx, substs),
);
// repr(transparent) types are allowed to have arbitrary ZSTs, not just
// PhantomData -- skip checking all ZST fields.
if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
continue;
}
let r = self.check_type_for_ffi(cache, field_ty);
match r {
FfiSafe => {
@ -712,14 +718,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// Check for a repr() attribute to specify the size of the
// discriminant.
if !def.repr.c() && def.repr.int.is_none() {
if !def.repr.c() && !def.repr.transparent() && def.repr.int.is_none() {
// Special-case types like `Option<extern fn()>`.
if !is_repr_nullable_ptr(cx, ty, def, substs) {
return FfiUnsafe {
ty: ty,
reason: "enum has no representation hint",
help: Some("consider adding a #[repr(...)] attribute \
to this enum"),
help: Some("consider adding a `#[repr(C)]`, \
`#[repr(transparent)]`, or integer `#[repr(...)]` \
attribute to this enum"),
};
}
}
@ -727,11 +734,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// Check the contained variants.
for variant in &def.variants {
for field in &variant.fields {
let arg = cx.normalize_erasing_regions(
let field_ty = cx.normalize_erasing_regions(
ParamEnv::reveal_all(),
field.ty(cx, substs),
);
let r = self.check_type_for_ffi(cache, arg);
// repr(transparent) types are allowed to have arbitrary ZSTs, not
// just PhantomData -- skip checking all ZST fields.
if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
continue;
}
let r = self.check_type_for_ffi(cache, field_ty);
match r {
FfiSafe => {}
FfiUnsafe { .. } => {

View file

@ -1310,7 +1310,7 @@ fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
check_transparent(tcx, span, def_id);
check_packed(tcx, span, def_id);
}
@ -1807,8 +1807,43 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De
return;
}
if adt.is_enum() {
if !tcx.features().transparent_enums {
emit_feature_err(&tcx.sess.parse_sess,
sym::transparent_enums,
sp,
GateIssue::Language,
"transparent enums are unstable");
}
if adt.variants.len() != 1 {
let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
tcx.hir().span_if_local(variant.def_id).unwrap()
}).collect();
let mut err = struct_span_err!(tcx.sess, sp, E0731,
"transparent enum needs exactly one variant, but has {}",
adt.variants.len());
if !variant_spans.is_empty() {
err.span_note(variant_spans, &format!("the following variants exist on `{}`",
tcx.def_path_str(def_id)));
}
err.emit();
if adt.variants.is_empty() {
// Don't bother checking the fields. No variants (and thus no fields) exist.
return;
}
}
}
if adt.is_union() && !tcx.features().transparent_unions {
emit_feature_err(&tcx.sess.parse_sess,
sym::transparent_unions,
sp,
GateIssue::Language,
"transparent unions are unstable");
}
// For each field, figure out if it's known to be a ZST and align(1)
let field_infos = adt.non_enum_variant().fields.iter().map(|field| {
let field_infos = adt.all_fields().map(|field| {
let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
let layout = tcx.layout_of(param_env.and(ty));
@ -1823,16 +1858,24 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count != 1 {
let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect();
struct_span_err!(tcx.sess, sp, E0690,
"transparent struct needs exactly one non-zero-sized field, but has {}",
non_zst_count)
.span_note(field_spans, "non-zero-sized field")
.emit();
let mut err = struct_span_err!(tcx.sess, sp, E0690,
"{}transparent {} needs exactly one non-zero-sized field, but has {}",
if adt.is_enum() { "the variant of a " } else { "" },
adt.descr(),
non_zst_count);
if !field_spans.is_empty() {
err.span_note(field_spans,
&format!("the following non-zero-sized fields exist on `{}`:",
tcx.def_path_str(def_id)));
}
err.emit();
}
for (span, zst, align1) in field_infos {
if zst && !align1 {
span_err!(tcx.sess, span, E0691,
"zero-sized field in transparent struct has alignment larger than 1");
"zero-sized field in transparent {} has alignment larger than 1",
adt.descr());
}
}
}
@ -1899,6 +1942,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
check_representable(tcx, sp, def_id);
check_transparent(tcx, sp, def_id);
}
fn report_unexpected_variant_res<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,

View file

@ -4484,7 +4484,7 @@ let _ = (2.0 as f32).neg();
E0690: r##"
A struct with the representation hint `repr(transparent)` had zero or more than
on fields that were not guaranteed to be zero-sized.
one fields that were not guaranteed to be zero-sized.
Erroneous code example:
@ -4519,8 +4519,8 @@ struct LengthWithUnit<U> {
"##,
E0691: r##"
A struct with the `repr(transparent)` representation hint contains a zero-sized
field that requires non-trivial alignment.
A struct, enum, or union with the `repr(transparent)` representation hint
contains a zero-sized field that requires non-trivial alignment.
Erroneous code example:
@ -4535,11 +4535,11 @@ struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent
// struct has alignment larger than 1
```
A transparent struct is supposed to be represented exactly like the piece of
data it contains. Zero-sized fields with different alignment requirements
potentially conflict with this property. In the example above, `Wrapper` would
have to be aligned to 32 bytes even though `f32` has a smaller alignment
requirement.
A transparent struct, enum, or union is supposed to be represented exactly like
the piece of data it contains. Zero-sized fields with different alignment
requirements potentially conflict with this property. In the example above,
`Wrapper` would have to be aligned to 32 bytes even though `f32` has a smaller
alignment requirement.
Consider removing the over-aligned zero-sized field:
@ -4569,7 +4569,6 @@ the alignment of the zero-sized type is less than or equal to the data field's
alignment.
"##,
E0699: r##"
A method was called on a raw pointer whose inner type wasn't completely known.
@ -4680,6 +4679,26 @@ match r {
```
"##,
E0731: r##"
An enum with the representation hint `repr(transparent)` had zero or more than
one variants.
Erroneous code example:
```compile_fail,E0731
#[repr(transparent)]
enum Status { // error: transparent enum needs exactly one variant, but has 2
Errno(u32),
Ok,
}
```
Because transparent enums are represented exactly like one of their variants at
run time, said variant must be uniquely determined. If there is no variant, or
if there are multiple variants, it is not clear how the enum should be
represented.
"##,
}
register_diagnostics! {

View file

@ -561,6 +561,12 @@ declare_features! (
// FIXME Create issue
(active, const_constructor, "1.37.0", Some(61456), None),
// #[repr(transparent)] on enums.
(active, transparent_enums, "1.37.0", Some(60405), None),
// #[repr(transparent)] on unions.
(active, transparent_unions, "1.37.0", Some(60405), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------

View file

@ -623,6 +623,8 @@ symbols! {
trait_alias,
transmute,
transparent,
transparent_enums,
transparent_unions,
trivial_bounds,
Try,
try_blocks,

View file

@ -1,4 +1,5 @@
// compile-flags: -C no-prepopulate-passes
// ignore-tidy-linelength
// ignore-arm
// ignore-mips
@ -7,36 +8,76 @@
// ignore-powerpc64
// See repr-transparent.rs
#![feature(transparent_enums, transparent_unions)]
#![crate_type="lib"]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Big([u32; 16]);
pub struct BigS([u32; 16]);
#[repr(transparent)]
pub struct BigW(Big);
pub struct TsBigS(BigS);
// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], %Big* [[BIG_ARG_ATTRS:.*]])
#[repr(transparent)]
pub union TuBigS {
field: BigS,
}
#[repr(transparent)]
pub enum TeBigS {
Variant(BigS),
}
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS:.*]], %BigS* [[BIGS_ARG_ATTRS:.*]])
#[no_mangle]
pub extern fn test_Big(_: Big) -> Big { loop {} }
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], %BigW* [[BIG_ARG_ATTRS]])
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS]], %TsBigS* [[BIGS_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS]], %TuBigS* [[BIGS_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS]], %"TeBigS::Variant"* [[BIGS_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
#[derive(Clone, Copy)]
#[repr(C)]
pub union BigU {
foo: [u32; 16],
}
#[repr(transparent)]
pub struct BigUw(BigU);
pub struct TsBigU(BigU);
#[repr(transparent)]
pub union TuBigU {
field: BigU,
}
#[repr(transparent)]
pub enum TeBigU {
Variant(BigU),
}
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], %BigU* [[BIGU_ARG_ATTRS:.*]])
#[no_mangle]
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], %BigUw* [[BIGU_ARG_ATTRS]])
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS:.*]], %TsBigU* [[BIGU_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS]], %TuBigU* [[BIGU_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS]], %"TeBigU::Variant"* [[BIGU_ARG_ATTRS]])
#[no_mangle]
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View file

@ -14,36 +14,76 @@
// ignore-x86_64
// See repr-transparent.rs
#![feature(transparent_enums, transparent_unions)]
#![crate_type="lib"]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Big([u32; 16]);
pub struct BigS([u32; 16]);
#[repr(transparent)]
pub struct BigW(Big);
pub struct TsBigS(BigS);
// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], [16 x i32]
#[repr(transparent)]
pub union TuBigS {
field: BigS,
}
#[repr(transparent)]
pub enum TeBigS {
Variant(BigS),
}
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS:.*]], [16 x i32]
#[no_mangle]
pub extern fn test_Big(_: Big) -> Big { loop {} }
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], [16 x i32]
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS]], [16 x i32]
#[no_mangle]
pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS]], [16 x i32]
#[no_mangle]
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS]], [16 x i32]
#[no_mangle]
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
#[derive(Clone, Copy)]
#[repr(C)]
pub union BigU {
foo: [u32; 16],
}
#[repr(transparent)]
pub struct BigUw(BigU);
pub struct TsBigU(BigU);
#[repr(transparent)]
pub union TuBigU {
field: BigU,
}
#[repr(transparent)]
pub enum TeBigU {
Variant(BigU),
}
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], [16 x i32]
#[no_mangle]
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], [16 x i32]
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS:.*]], [16 x i32]
#[no_mangle]
pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS]], [16 x i32]
#[no_mangle]
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS]], [16 x i32]
#[no_mangle]
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View file

@ -3,36 +3,76 @@
// only-mips64
// See repr-transparent.rs
#![feature(transparent_enums, transparent_unions)]
#![crate_type="lib"]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Big([u32; 16]);
pub struct BigS([u32; 16]);
#[repr(transparent)]
pub struct BigW(Big);
pub struct TsBigS(BigS);
// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], [8 x i64]
#[repr(transparent)]
pub union TuBigS {
field: BigS,
}
#[repr(transparent)]
pub enum TeBigS {
Variant(BigS),
}
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS:.*]], [8 x i64]
#[no_mangle]
pub extern fn test_Big(_: Big) -> Big { loop {} }
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], [8 x i64]
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS]], [8 x i64]
#[no_mangle]
pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS]], [8 x i64]
#[no_mangle]
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS]], [8 x i64]
#[no_mangle]
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
#[derive(Clone, Copy)]
#[repr(C)]
pub union BigU {
foo: [u32; 16],
}
#[repr(transparent)]
pub struct BigUw(BigU);
pub struct TsBigU(BigU);
#[repr(transparent)]
pub union TuBigU {
field: BigU,
}
#[repr(transparent)]
pub enum TeBigU {
Variant(BigU),
}
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], [8 x i64]
#[no_mangle]
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], [8 x i64]
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS:.*]], [8 x i64]
#[no_mangle]
pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS]], [8 x i64]
#[no_mangle]
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS]], [8 x i64]
#[no_mangle]
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

View file

@ -1,13 +1,16 @@
// compile-flags: -C no-prepopulate-passes
#![crate_type="lib"]
#![feature(repr_simd)]
#![feature(repr_simd, transparent_enums, transparent_unions)]
use std::marker::PhantomData;
#[derive(Copy, Clone)]
pub struct Zst1;
#[derive(Copy, Clone)]
pub struct Zst2(());
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct F32(f32);
@ -112,6 +115,44 @@ pub struct StructWithProjection(<f32 as Mirror>::It);
#[no_mangle]
pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
#[repr(transparent)]
pub enum EnumF32 {
Variant(F32)
}
// CHECK: define float @test_EnumF32(float %arg0)
#[no_mangle]
pub extern fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} }
#[repr(transparent)]
pub enum EnumF32WithZsts {
Variant(Zst1, F32, Zst2)
}
// CHECK: define float @test_EnumF32WithZsts(float %arg0)
#[no_mangle]
pub extern fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} }
#[repr(transparent)]
pub union UnionF32 {
field: F32,
}
// CHECK: define float @test_UnionF32(float %arg0)
#[no_mangle]
pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
#[repr(transparent)]
pub union UnionF32WithZsts {
zst1: Zst1,
field: F32,
zst2: Zst2,
}
// CHECK: define float @test_UnionF32WithZsts(float %arg0)
#[no_mangle]
pub extern fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} }
// All that remains to be tested are aggregates. They are tested in separate files called repr-
// transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR

View file

@ -1,4 +1,6 @@
// run-pass
#![feature(transparent_unions)]
use std::mem::size_of;
use std::num::NonZeroUsize;
use std::ptr::NonNull;
@ -10,6 +12,11 @@ trait Mirror { type Image; }
impl<T> Mirror for T { type Image = T; }
struct ParamTypeStruct<T>(T);
struct AssocTypeStruct<T>(<T as Mirror>::Image);
#[repr(transparent)]
union MaybeUninitUnion<T: Copy> {
_value: T,
_uninit: (),
}
fn main() {
// Functions
@ -29,9 +36,12 @@ fn main() {
// Pointers - Box<T>
assert_eq!(size_of::<Box<isize>>(), size_of::<Option<Box<isize>>>());
// The optimization can't apply to raw pointers
// The optimization can't apply to raw pointers or unions with a ZST field.
assert!(size_of::<Option<*const isize>>() != size_of::<*const isize>());
assert!(Some(0 as *const isize).is_some()); // Can't collapse None to null
assert_ne!(size_of::<fn(isize)>(), size_of::<Option<MaybeUninitUnion<fn(isize)>>>());
assert_ne!(size_of::<&str>(), size_of::<Option<MaybeUninitUnion<&str>>>());
assert_ne!(size_of::<NonNull<isize>>(), size_of::<Option<MaybeUninitUnion<NonNull<isize>>>>());
struct Foo {
_a: Box<isize>

View file

@ -1,6 +1,6 @@
#![feature(repr_simd)]
#[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union
#[repr(C)] //~ ERROR: attribute should be applied to struct, enum, or union
fn f() {}
#[repr(C)]

View file

@ -1,10 +1,10 @@
error[E0517]: attribute should be applied to struct, enum or union
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/attr-usage-repr.rs:3:8
|
LL | #[repr(C)]
| ^
LL | fn f() {}
| --------- not a struct, enum or union
| --------- not a struct, enum, or union
error[E0517]: attribute should be applied to enum
--> $DIR/attr-usage-repr.rs:15:8

View file

@ -1,10 +1,10 @@
error[E0517]: attribute should be applied to struct, enum or union
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/E0517.rs:1:8
|
LL | #[repr(C)]
| ^
LL | type Foo = u8;
| -------------- not a struct, enum or union
| -------------- not a struct, enum, or union
error[E0517]: attribute should be applied to struct or union
--> $DIR/E0517.rs:4:8
@ -22,14 +22,14 @@ LL | #[repr(u8)]
LL | struct Foo3 {bar: bool, baz: bool}
| ---------------------------------- not an enum
error[E0517]: attribute should be applied to struct, enum or union
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/E0517.rs:10:8
|
LL | #[repr(C)]
| ^
LL | / impl Foo3 {
LL | | }
| |_- not a struct, enum or union
| |_- not a struct, enum, or union
error: aborting due to 4 previous errors

View file

@ -0,0 +1,6 @@
#[repr(transparent)]
enum OkButUnstableEnum { //~ ERROR transparent enums are unstable
Foo((), String, ()),
}
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0658]: transparent enums are unstable
--> $DIR/feature-gate-transparent_enums.rs:2:1
|
LL | / enum OkButUnstableEnum {
LL | | Foo((), String, ()),
LL | | }
| |_^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60405
= help: add #![feature(transparent_enums)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,7 @@
#[repr(transparent)]
union OkButUnstableUnion { //~ ERROR transparent unions are unstable
field: u8,
zst: (),
}
fn main() {}

View file

@ -0,0 +1,15 @@
error[E0658]: transparent unions are unstable
--> $DIR/feature-gate-transparent_unions.rs:2:1
|
LL | / union OkButUnstableUnion {
LL | | field: u8,
LL | | zst: (),
LL | | }
| |_^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60405
= help: add #![feature(transparent_unions)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -9,7 +9,7 @@ note: lint level defined here
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -24,7 +24,7 @@ error: `extern` block uses type `A` which is not FFI-safe: this struct has unspe
LL | fn bar(x: B);
| ^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -39,7 +39,7 @@ error: `extern` block uses type `A` which is not FFI-safe: this struct has unspe
LL | fn qux(x: A2);
| ^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -54,7 +54,7 @@ error: `extern` block uses type `A` which is not FFI-safe: this struct has unspe
LL | fn quux(x: B2);
| ^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -69,7 +69,7 @@ error: `extern` block uses type `A` which is not FFI-safe: this struct has unspe
LL | fn fred(x: D);
| ^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-14309.rs:4:1
|

View file

@ -10,7 +10,7 @@ note: lint level defined here
LL | #![deny(warnings)]
| ^^^^^^^^
= note: #[deny(improper_ctypes)] implied by #[deny(warnings)]
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/issue-16250.rs:3:1
|

View file

@ -1,4 +1,4 @@
fn main() {
#[inline] struct Foo; //~ ERROR attribute should be applied to function or closure
#[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union
#[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum, or union
}

View file

@ -4,11 +4,11 @@ error[E0518]: attribute should be applied to function or closure
LL | #[inline] struct Foo;
| ^^^^^^^^^ ----------- not a function or closure
error[E0517]: attribute should be applied to struct, enum or union
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/issue-31769.rs:3:12
|
LL | #[repr(C)] fn foo() {}
| ^ ----------- not a struct, enum or union
| ^ ----------- not a struct, enum, or union
error: aborting due to 2 previous errors

View file

@ -32,7 +32,7 @@ error[E0517]: attribute should not be applied to a statement
LL | #[repr(nothing)]
| ^^^^^^^^^^^^^^^^
LL | let _x = 0;
| ----------- not a struct, enum or union
| ----------- not a struct, enum, or union
error[E0517]: attribute should not be applied to an expression
--> $DIR/issue-43988.rs:18:5
@ -42,7 +42,7 @@ LL | #[repr(something_not_real)]
LL | / loop {
LL | | ()
LL | | };
| |_____- not defining a struct, enum or union
| |_____- not defining a struct, enum, or union
error[E0517]: attribute should not be applied to a statement
--> $DIR/issue-43988.rs:24:5
@ -50,7 +50,7 @@ error[E0517]: attribute should not be applied to a statement
LL | #[repr]
| ^^^^^^^
LL | let _y = "123";
| --------------- not a struct, enum or union
| --------------- not a struct, enum, or union
error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-43988.rs:31:5
@ -64,7 +64,7 @@ error[E0517]: attribute should not be applied to an expression
--> $DIR/issue-43988.rs:35:14
|
LL | let _z = #[repr] 1;
| ^^^^^^^ - not defining a struct, enum or union
| ^^^^^^^ - not defining a struct, enum, or union
error: aborting due to 9 previous errors

View file

@ -1,3 +1,4 @@
#![feature(transparent_enums, transparent_unions)]
#![deny(improper_ctypes)]
#![allow(dead_code)]
@ -18,7 +19,17 @@ enum U8 { A, B, C }
enum Isize { A, B, C }
#[repr(transparent)]
struct Transparent<T>(T, std::marker::PhantomData<Z>);
struct TransparentStruct<T>(T, std::marker::PhantomData<Z>);
#[repr(transparent)]
enum TransparentEnum<T> {
Variant(T, std::marker::PhantomData<Z>),
}
#[repr(transparent)]
union TransparentUnion<T: Copy> {
field: T,
}
struct Rust<T>(T);
@ -47,7 +58,10 @@ extern {
fn nonzero_i128(x: Option<num::NonZeroI128>);
//~^ ERROR 128-bit integers don't currently have a known stable ABI
fn nonzero_isize(x: Option<num::NonZeroIsize>);
fn repr_transparent(x: Option<Transparent<num::NonZeroU8>>);
fn transparent_struct(x: Option<TransparentStruct<num::NonZeroU8>>);
fn transparent_enum(x: Option<TransparentEnum<num::NonZeroU8>>);
fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
//~^ ERROR enum has no representation hint
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
}

View file

@ -1,74 +1,82 @@
error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:27:13
--> $DIR/lint-ctypes-enum.rs:38:13
|
LL | fn uf(x: U);
| ^
|
note: lint level defined here
--> $DIR/lint-ctypes-enum.rs:1:9
--> $DIR/lint-ctypes-enum.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(...)] attribute to this enum
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:7:1
--> $DIR/lint-ctypes-enum.rs:8:1
|
LL | enum U { A }
| ^^^^^^^^^^^^
error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:28:13
--> $DIR/lint-ctypes-enum.rs:39:13
|
LL | fn bf(x: B);
| ^
|
= help: consider adding a #[repr(...)] attribute to this enum
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:8:1
--> $DIR/lint-ctypes-enum.rs:9:1
|
LL | enum B { C, D }
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:29:13
--> $DIR/lint-ctypes-enum.rs:40:13
|
LL | fn tf(x: T);
| ^
|
= help: consider adding a #[repr(...)] attribute to this enum
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
note: type defined here
--> $DIR/lint-ctypes-enum.rs:9:1
--> $DIR/lint-ctypes-enum.rs:10:1
|
LL | enum T { E, F, G }
| ^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:40:23
--> $DIR/lint-ctypes-enum.rs:51:23
|
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:47:23
--> $DIR/lint-ctypes-enum.rs:58:23
|
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:63:28
|
LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:51:20
--> $DIR/lint-ctypes-enum.rs:65:20
|
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(...)] attribute to this enum
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:52:20
--> $DIR/lint-ctypes-enum.rs:66:20
|
LL | fn no_result(x: Result<(), num::NonZeroI32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(...)] attribute to this enum
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
error: aborting due to 7 previous errors
error: aborting due to 8 previous errors

View file

@ -9,7 +9,7 @@ note: lint level defined here
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/lint-ctypes.rs:24:1
|
@ -22,7 +22,7 @@ error: `extern` block uses type `Foo` which is not FFI-safe: this struct has uns
LL | pub fn ptr_type2(size: *const Foo);
| ^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
note: type defined here
--> $DIR/lint-ctypes.rs:24:1
|
@ -51,7 +51,7 @@ error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: th
LL | pub fn box_type(p: Box<u32>);
| ^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
--> $DIR/lint-ctypes.rs:51:25
@ -142,7 +142,7 @@ error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: th
LL | pub fn fn_contained(p: RustBadRet);
| ^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes.rs:64:32
@ -164,7 +164,7 @@ error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: th
LL | pub fn transparent_fn(p: TransparentBadFn);
| ^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
error: aborting due to 20 previous errors

View file

@ -1,26 +1,5 @@
// See also repr-transparent.rs
#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
enum Void {} //~| ERROR should be applied to struct
#[repr(transparent)] //~ ERROR should be applied to struct
enum FieldlessEnum {
Foo,
Bar,
}
#[repr(transparent)] //~ ERROR should be applied to struct
enum Enum {
Foo(String),
Bar(u32),
}
#[repr(transparent)] //~ ERROR should be applied to struct
union Foo {
u: u32,
s: i32
}
#[repr(transparent)] //~ ERROR should be applied to struct
fn cant_repr_this() {}

View file

@ -1,69 +1,19 @@
error[E0517]: attribute should be applied to struct
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/repr-transparent-other-items.rs:3:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | enum Void {}
| ------------ not a struct
error[E0517]: attribute should be applied to struct
--> $DIR/repr-transparent-other-items.rs:6:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | / enum FieldlessEnum {
LL | | Foo,
LL | | Bar,
LL | | }
| |_- not a struct
error[E0517]: attribute should be applied to struct
--> $DIR/repr-transparent-other-items.rs:12:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | / enum Enum {
LL | | Foo(String),
LL | | Bar(u32),
LL | | }
| |_- not a struct
error[E0517]: attribute should be applied to struct
--> $DIR/repr-transparent-other-items.rs:18:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | / union Foo {
LL | | u: u32,
LL | | s: i32
LL | | }
| |_- not a struct
error[E0517]: attribute should be applied to struct
--> $DIR/repr-transparent-other-items.rs:24:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | fn cant_repr_this() {}
| ---------------------- not a struct
| ---------------------- not a struct, enum, or union
error[E0517]: attribute should be applied to struct
--> $DIR/repr-transparent-other-items.rs:27:8
error[E0517]: attribute should be applied to struct, enum, or union
--> $DIR/repr-transparent-other-items.rs:6:8
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^
LL | static CANT_REPR_THIS: u32 = 0;
| ------------------------------- not a struct
| ------------------------------- not a struct, enum, or union
error[E0084]: unsupported representation for zero-variant enum
--> $DIR/repr-transparent-other-items.rs:3:1
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^^^^^^^^^^
LL | enum Void {}
| ------------ zero-variant enum
error: aborting due to 2 previous errors
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0084, E0517.
For more information about an error, try `rustc --explain E0084`.
For more information about this error, try `rustc --explain E0517`.

View file

@ -3,7 +3,7 @@
// - repr-transparent-other-reprs.rs
// - repr-transparent-other-items.rs
#![feature(repr_align)]
#![feature(repr_align, transparent_enums, transparent_unions)]
use std::marker::PhantomData;
@ -39,4 +39,36 @@ struct ZstAlign32<T>(PhantomData<T>);
#[repr(transparent)]
struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
enum Void {}
//~^ ERROR transparent enum needs exactly one variant, but has 0
#[repr(transparent)]
enum FieldlessEnum { //~ ERROR transparent enum needs exactly one non-zero-sized field, but has 0
Foo,
}
#[repr(transparent)]
enum TooManyFieldsEnum {
Foo(u32, String),
}
//~^^^ ERROR transparent enum needs exactly one non-zero-sized field, but has 2
#[repr(transparent)]
enum TooManyVariants { //~ ERROR transparent enum needs exactly one variant, but has 2
Foo(String),
Bar,
}
#[repr(transparent)]
union UnitUnion { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 0
u: (),
}
#[repr(transparent)]
union TooManyFields { //~ ERROR transparent union needs exactly one non-zero-sized field, but has 2
u: u32,
s: i32
}
fn main() {}

View file

@ -3,32 +3,24 @@ error[E0690]: transparent struct needs exactly one non-zero-sized field, but has
|
LL | struct NoFields;
| ^^^^^^^^^^^^^^^^
|
= note: non-zero-sized field
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:14:1
|
LL | struct ContainsOnlyZst(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: non-zero-sized field
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]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: non-zero-sized field
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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: non-zero-sized field
error[E0690]: transparent struct needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:24:1
@ -36,7 +28,7 @@ error[E0690]: transparent struct needs exactly one non-zero-sized field, but has
LL | struct MultipleNonZst(u8, u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: non-zero-sized field
note: the following non-zero-sized fields exist on `MultipleNonZst`:
--> $DIR/repr-transparent.rs:24:23
|
LL | struct MultipleNonZst(u8, u8);
@ -48,7 +40,7 @@ error[E0690]: transparent struct needs exactly one non-zero-sized field, but has
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: non-zero-sized field
note: the following non-zero-sized fields exist on `StructWithProjection`:
--> $DIR/repr-transparent.rs:30:33
|
LL | pub struct StructWithProjection(f32, <f32 as Mirror>::It);
@ -66,7 +58,85 @@ error[E0691]: zero-sized field in transparent struct has alignment larger than 1
LL | struct GenericAlign<T>(ZstAlign32<T>, u32);
| ^^^^^^^^^^^^^
error: aborting due to 8 previous errors
error[E0084]: unsupported representation for zero-variant enum
--> $DIR/repr-transparent.rs:42:1
|
LL | #[repr(transparent)]
| ^^^^^^^^^^^^^^^^^^^^
LL | enum Void {}
| ------------ zero-variant enum
Some errors have detailed explanations: E0690, E0691.
For more information about an error, try `rustc --explain E0690`.
error[E0731]: transparent enum needs exactly one variant, but has 0
--> $DIR/repr-transparent.rs:43:1
|
LL | enum Void {}
| ^^^^^^^^^^^^
error[E0690]: the variant of a transparent enum needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:47:1
|
LL | / enum FieldlessEnum {
LL | | Foo,
LL | | }
| |_^
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 | | Foo(u32, String),
LL | | }
| |_^
|
note: the following non-zero-sized fields exist on `TooManyFieldsEnum`:
--> $DIR/repr-transparent.rs:53:9
|
LL | Foo(u32, String),
| ^^^ ^^^^^^
error[E0731]: transparent enum needs exactly one variant, but has 2
--> $DIR/repr-transparent.rs:58:1
|
LL | / enum TooManyVariants {
LL | | Foo(String),
LL | | Bar,
LL | | }
| |_^
|
note: the following variants exist on `TooManyVariants`
--> $DIR/repr-transparent.rs:59:5
|
LL | Foo(String),
| ^^^^^^^^^^^
LL | Bar,
| ^^^
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 0
--> $DIR/repr-transparent.rs:64:1
|
LL | / union UnitUnion {
LL | | u: (),
LL | | }
| |_^
error[E0690]: transparent union needs exactly one non-zero-sized field, but has 2
--> $DIR/repr-transparent.rs:69:1
|
LL | / union TooManyFields {
LL | | u: u32,
LL | | s: i32
LL | | }
| |_^
|
note: the following non-zero-sized fields exist on `TooManyFields`:
--> $DIR/repr-transparent.rs:70:5
|
LL | u: u32,
| ^^^^^^
LL | s: i32
| ^^^^^^
error: aborting due to 15 previous errors
Some errors have detailed explanations: E0084, E0690, E0691, E0731.
For more information about an error, try `rustc --explain E0084`.

View file

@ -9,7 +9,7 @@ note: lint level defined here
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(C)] attribute to this union
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
note: type defined here
--> $DIR/union-repr-c.rs:9:1
|