-
Notifications
You must be signed in to change notification settings - Fork 583
Glossary: add new entry documenting zero-sized types #2203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -211,9 +211,68 @@ r[glossary.uninhabited] | |
|
|
||
| A type is uninhabited if it has no constructors and therefore can never be instantiated. An uninhabited type is "empty" in the sense that there are no values of the type. The canonical example of an uninhabited type is the [never type] `!`, or an enum with no variants `enum Never { }`. Opposite of [Inhabited](#inhabited). | ||
|
|
||
| r[glossary.zst] | ||
| ### Zero-sized type (ZST) | ||
|
|
||
| A type is zero sized (a ZST) if its size is 0. Such types have at most one possible value. Examples include: | ||
|
|
||
| - The [unit type] (see [layout.tuple.unit]). | ||
| - [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(C)]` structs with no fields ([unit-like structs]) or where all fields are zero-sized (see [layout.repr.c.struct.size-field-offset]). | ||
| - `#[repr(transparent)]` structs with no fields ([unit-like structs]) or where all fields are zero-sized (see [layout.repr.transparent.layout-abi]). | ||
|
Comment on lines
+223
to
+224
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In prose, we'd just say " |
||
| - [Arrays] of zero-sized types (see [layout.array]). | ||
|
DanielEScherzer marked this conversation as resolved.
|
||
| - [Arrays] of length zero (see [layout.array]). | ||
| - [Unions] of zero-sized types (see [items.union.common-storage]). | ||
|
|
||
| ```rust | ||
| # use core::mem::{size_of, size_of_val}; | ||
| fn f() {} | ||
| struct S(u8); | ||
| enum E{ V(u8) } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the missing space here. |
||
| #[repr(C)] | ||
| struct C1 {} | ||
| #[repr(C)] | ||
| struct C2 { | ||
| f1: (), | ||
| f2: [(); 10], | ||
| f3: [u8; 0], | ||
| f4: C1, | ||
| } | ||
| #[repr(transparent)] | ||
| struct T1 {} | ||
| #[repr(transparent)] | ||
| struct T2 { | ||
| f1: (), | ||
| f2: [(); 10], | ||
| f3: [u8; 0], | ||
| } | ||
| union U { | ||
| f1: (), | ||
| f2: [(); 10], | ||
| f3: [u8; 0], | ||
| } | ||
| assert_eq!(0, size_of::<()>()); | ||
| assert_eq!(0, size_of_val(&f)); | ||
| // Note that here we are checking the size of the constructors, *not* the | ||
| // underlying type, for `S` and `E::V`. The constructors just have the same | ||
| // names as the types. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could use some rewording. This is value position, so it's syntactically clear the name doesn't refer here to a type. Also, Since the corresponding values couldn't be constructed in this way (due to needing arguments), it might be OK to just drop this comment. |
||
| assert_eq!(0, size_of_val(&S)); | ||
| assert_eq!(0, size_of_val(&E::V)); | ||
| assert_eq!(0, size_of::<C1>()); | ||
| assert_eq!(0, size_of::<C2>()); | ||
| assert_eq!(0, size_of::<T1>()); | ||
| assert_eq!(0, size_of::<T2>()); | ||
| assert_eq!(0, size_of::<[(); 10]>()); | ||
| assert_eq!(0, size_of::<[u8; 0]>()); | ||
| assert_eq!(0, size_of::<U>()); | ||
| ``` | ||
|
|
||
| [`extern` blocks]: items.extern | ||
| [`extern fn`]: items.fn.extern | ||
| [alignment]: type-layout.md#size-and-alignment | ||
| [arrays]: type.array | ||
| [associated item]: #associated-item | ||
| [attributes]: attributes.md | ||
| [*entity*]: names.md | ||
|
|
@@ -222,6 +281,7 @@ A type is uninhabited if it has no constructors and therefore can never be insta | |
| [enums]: items/enumerations.md | ||
| [fields]: expressions/field-expr.md | ||
| [free item]: #free-item | ||
| [function items]: type.fn-item | ||
| [generic parameters]: items/generics.md | ||
| [identifier]: identifiers.md | ||
| [identifiers]: identifiers.md | ||
|
|
@@ -252,5 +312,7 @@ A type is uninhabited if it has no constructors and therefore can never be insta | |
| [types]: types.md | ||
| [undefined-behavior]: behavior-considered-undefined.md | ||
| [unions]: items/unions.md | ||
| [unit type]: type.tuple.unit | ||
| [unit-like structs]: items.struct.unit | ||
| [variable bindings]: patterns.md | ||
| [visibility rules]: visibility-and-privacy.md | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,7 +59,7 @@ mutability aren't placed in memory marked as read only. | |
| r[lang-types.phantom-data] | ||
| ## `PhantomData<T>` | ||
|
|
||
| [`std::marker::PhantomData<T>`] is a zero-sized, minimum alignment, type that | ||
| [`std::marker::PhantomData<T>`] is a [zero-sized], minimum alignment, type that | ||
| is considered to own a `T` for the purposes of [variance], [drop check], and | ||
| [auto traits](#auto-traits). | ||
|
|
||
|
|
@@ -246,6 +246,7 @@ These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound | |
| [test functions]: attributes/testing.md#the-test-attribute | ||
| [the standard library]: std | ||
| [trait object]: types/trait-object.md | ||
| [zero-sized]: glossary.zst | ||
| [Tuples]: types/tuple.md | ||
| [Type parameters]: types/parameters.md | ||
| [variance]: subtyping.md#variance | ||
|
Comment on lines
+249
to
252
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Reference isn't perfecly consistent about this, but in this case, the sorting is insensitive to case. |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ r[layout.properties.align] | |
| The *alignment* of a value specifies what addresses are valid to store the value at. A value of alignment `n` must only be stored at an address that is a multiple of n. For example, a value with an alignment of 2 must be stored at an even address, while a value with an alignment of 1 can be stored at any address. Alignment is measured in bytes, and must be at least 1, and always a power of 2. The alignment of a value can be checked with the [`align_of_val`] function. | ||
|
|
||
| r[layout.properties.size] | ||
| The *size* of a value is the offset in bytes between successive elements in an array with that item type including alignment padding. The size of a value is always a multiple of its alignment. Note that some types are zero-sized; 0 is considered a multiple of any alignment (for example, on some platforms, the type `[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with the [`size_of_val`] function. | ||
| The *size* of a value is the offset in bytes between successive elements in an array with that item type including alignment padding. The size of a value is always a multiple of its alignment. Note that some types are [zero-sized]; 0 is considered a multiple of any alignment (for example, on some platforms, the type `[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with the [`size_of_val`] function. | ||
|
|
||
| r[layout.properties.sized] | ||
| Types where all values have the same size and alignment, and both are known at compile time, implement the [`Sized`] trait and can be checked with the [`size_of`] and [`align_of`] functions. Types that are not [`Sized`] are known as [dynamically sized types]. Since all values of a `Sized` type share the same size and alignment, we refer to those shared values as the size of the type and the alignment of the type respectively. | ||
|
|
@@ -94,7 +94,7 @@ r[layout.tuple.def] | |
| Tuples are laid out according to the [`Rust` representation][`Rust`]. | ||
|
|
||
| r[layout.tuple.unit] | ||
| The exception to this is the unit tuple (`()`), which is guaranteed as a zero-sized type to have a size of 0 and an alignment of 1. | ||
| The exception to this is the unit tuple (`()`), which is guaranteed as a [zero-sized type] to have a size of 0 and an alignment of 1. | ||
|
|
||
| r[layout.trait-object] | ||
| ## Trait object layout | ||
|
|
@@ -178,7 +178,7 @@ The only data layout guarantees made by this representation are those required f | |
| r[layout.repr.rust.layout.struct] | ||
| For [structs], it is further guaranteed that the fields do not overlap. That is, the fields can be ordered such that the offset plus the size of any field is less than or equal to the offset of the next field in the ordering. The ordering does not have to be the same as the order in which the fields are specified in the declaration of the type. | ||
|
|
||
| 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. | ||
| 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.unspecified] | ||
| There are no other guarantees of data layout made by this representation. | ||
|
|
@@ -248,7 +248,7 @@ struct.size = current_offset + padding_needed_for(current_offset, struct.alignme | |
| > This pseudocode uses a naive algorithm that ignores overflow issues for the sake of clarity. To perform memory layout computations in actual code, use [`Layout`]. | ||
|
|
||
| > [!NOTE] | ||
| > This algorithm can produce zero-sized structs. In C, an empty struct declaration like `struct Foo { }` is illegal. However, both gcc and clang support options to enable such structs, and assign them size zero. C++, in contrast, gives empty structs a size of 1, unless they are inherited from or they are fields that have the `[[no_unique_address]]` attribute, in which case they do not increase the overall size of the struct. | ||
| > This algorithm can produce [zero-sized structs]. In C, an empty struct declaration like `struct Foo { }` is illegal. However, both gcc and clang support options to enable such structs, and assign them size zero. C++, in contrast, gives empty structs a size of 1, unless they are inherited from or they are fields that have the `[[no_unique_address]]` attribute, in which case they do not increase the overall size of the struct. | ||
|
|
||
| r[layout.repr.c.union] | ||
| #### `#[repr(C)]` Unions | ||
|
|
@@ -561,6 +561,10 @@ Because this representation delegates type layout to another type, it cannot be | |
| [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 type]: glossary.zst | ||
| [zero-sized types]: glossary.zst | ||
| [zero-sized structs]: glossary.zst | ||
|
Comment on lines
+564
to
+567
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "zero-sized structs" would sort before "zero-sized type". |
||
| [`PhantomData<T>`]: special-types-and-traits.md#phantomdatat | ||
| [`Rust`]: #the-rust-representation | ||
| [`C`]: #the-c-representation | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please link "tuple-like structs" and "tuple-like enum variants".
View changes since the review