diff --git a/src/glossary.md b/src/glossary.md index 6a7afcfaae..e48bcf4f9c 100644 --- a/src/glossary.md +++ b/src/glossary.md @@ -220,8 +220,10 @@ A type is zero sized (a ZST) if its size is 0. Such types have at most one possi - [Function items] (see [type.fn-item.intro]). - The constructors of [tuple-like structs] (see [type.fn-item.intro]). - The constructors of [tuple-like enum variants] (see [type.fn-item.intro]). +- `repr(Rust)` [structs] with no fields or where all fields are zero sized (see [layout.repr.rust.struct-zst]). - `repr(C)` [structs] with no fields or where all fields are zero-sized (see [layout.repr.c.struct.size-field-offset]). - `repr(transparent)` [structs] with no fields or where all fields are zero-sized (see [layout.repr.transparent.layout-abi]). +- `repr(Rust)` [enums] (without a [primitive representation] specified) with a single [field-struct-like variant], a single [unit-struct-like variant], or a single [tuple-struct-like variant] and where the struct-like thing has no fields or where all of the fields are zero sized (see [layout.repr.rust.enum-struct-like-zst]). - [Arrays] of zero-sized types (see [layout.array]). - [Arrays] of length zero (see [layout.array]). - [Unions] of zero-sized types (see [items.union.common-storage]). @@ -231,6 +233,13 @@ A type is zero sized (a ZST) if its size is 0. Such types have at most one possi fn f() {} struct S(u8); enum E { V(u8) } +struct UnitLike; +struct NoFields {} +struct OnlyZST { + f1: (), + f2: [(); 10], + f3: [u8; 0], +} #[repr(C)] struct C1 {} #[repr(C)] @@ -253,10 +262,36 @@ union U { f2: [(); 10], f3: [u8; 0], } +# /// An enum with a single field-struct-like variant with all fields +# /// being ZSTs. +enum E2 { + V1 { f1: (), f2: [(); 10] }, +} +# /// An enum with a single field-struct-like variant with no fields. +enum E3 { + V1 {}, +} +# /// An enum with a single unit-struct-like variant. +enum E4 { + V1, +} +# /// An enum with a single tuple-struct-like variant with all fields +# /// being ZSTs. +enum E5 { + V1 ((), [(); 10]), +} +# /// An enum with a single tuple-struct-like variant with no fields. +enum E6 { + V1 (), +} + assert_eq!(0, size_of::<()>()); assert_eq!(0, size_of_val(&f)); assert_eq!(0, size_of_val(&S)); assert_eq!(0, size_of_val(&E::V)); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); assert_eq!(0, size_of::()); assert_eq!(0, size_of::()); assert_eq!(0, size_of::()); @@ -264,6 +299,11 @@ assert_eq!(0, size_of::()); assert_eq!(0, size_of::<[(); 10]>()); assert_eq!(0, size_of::<[u8; 0]>()); assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); +assert_eq!(0, size_of::()); ``` [`extern` blocks]: items.extern @@ -276,6 +316,7 @@ assert_eq!(0, size_of::()); [crate]: crates-and-source-files.md [dyn compatibility]: items/traits.md#dyn-compatibility [enums]: items/enumerations.md +[field-struct-like variant]: EnumVariantStruct [fields]: expressions/field-expr.md [free item]: #free-item [function items]: type.fn-item @@ -300,10 +341,12 @@ assert_eq!(0, size_of::()); [never type]: types/never.md [*path*]: paths.md [Paths]: paths.md +[primitive representation]: layout.repr.primitive [*scope*]: names/scopes.md [structs]: items/structs.md [tuple-like enum variants]: items.enum.constructor-namespace [tuple-like structs]: items.struct.tuple +[tuple-struct-like variant]: EnumVariantTuple [trait object types]: types/trait-object.md [traits]: items/traits.md [turbofish test]: https://github.com/rust-lang/rust/blob/1.58.0/src/test/ui/parser/bastion-of-the-turbofish.rs @@ -312,5 +355,6 @@ assert_eq!(0, size_of::()); [undefined-behavior]: behavior-considered-undefined.md [unions]: items/unions.md [unit type]: type.tuple.unit +[unit-struct-like variant]: EnumVariant [variable bindings]: patterns.md [visibility rules]: visibility-and-privacy.md diff --git a/src/type-layout.md b/src/type-layout.md index 2ee902aef0..2d17f7e0ce 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -180,6 +180,12 @@ For [structs], it is further guaranteed that the fields do not overlap. That is, Be aware that this guarantee does not imply that the fields have distinct addresses: [zero-sized types] may have the same address as other fields in the same struct. +r[layout.repr.rust.struct-zst] +For [structs] with no fields or where all fields are [zero sized], it is further guaranteed that the structs are themselves [zero sized]. + +r[layout.repr.rust.enum-struct-like-zst] +For [enums] (without a [primitive representation] specified) with a single [field-struct-like variant], a single [unit-struct-like variant], or a single [tuple-struct-like variant] and where the struct-like thing has no fields or where all of the fields are [zero sized], the enums themselves are [zero sized]. + r[layout.repr.rust.unspecified] There are no other guarantees of data layout made by this representation. @@ -556,18 +562,24 @@ Because this representation delegates type layout to another type, it cannot be [`Sized`]: std::marker::Sized [`Copy`]: std::marker::Copy [dynamically sized types]: dynamically-sized-types.md +[enums]: items/enumerations.md [field-less enums]: items/enumerations.md#field-less-enum +[field-struct-like variant]: EnumVariantStruct [fn-abi-compatibility]: ../core/primitive.fn.md#abi-compatibility [enumerations]: items/enumerations.md [zero-variant enums]: items/enumerations.md#zero-variant-enums [undefined behavior]: behavior-considered-undefined.md +[zero sized]: glossary.zst [zero-sized]: glossary.zst [zero-sized type]: glossary.zst [zero-sized types]: glossary.zst [`PhantomData`]: special-types-and-traits.md#phantomdatat [`Rust`]: #the-rust-representation [`C`]: #the-c-representation +[primitive representation]: #primitive-representations [primitive representations]: #primitive-representations [structs]: items/structs.md [`transparent`]: #the-transparent-representation +[tuple-struct-like variant]: EnumVariantTuple +[unit-struct-like variant]: EnumVariant [`Layout`]: std::alloc::Layout