Skip to content
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

Spec: Improve Definition of Type Layout #1654

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
Remove extraneous Whitespace
chorman0773 committed Oct 17, 2024
commit f67be5cdabb8dcc2252fda6b3039f090df18b87a
24 changes: 11 additions & 13 deletions src/type-layout.md
Original file line number Diff line number Diff line change
@@ -146,17 +146,17 @@ r[layout.aggregate]

r[layout.aggregate.intro] Aggregate types, `struct`s and `union`s, determine the layout based on its fields, and the [repr][layout.repr] attribute. Each field is categorized by its alignment and size, and an offset within that struct which, by default, is a multiple of its alignment.

r[layout.aggregate.struct-offsets] The fields of a `struct` have offsets such that none of the fields overlap within the `struct`.
r[layout.aggregate.struct-offsets] The fields of a `struct` have offsets such that none of the fields overlap within the `struct`.

r[layout.aggregate.struct-size-align]
The size of a `struct` is at least such that each field can be placed within the struct's storage, and the size is a multiple of its alignment. The alignment of a `struct`, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields.
The size of a `struct` is at least such that each field can be placed within the struct's storage, and the size is a multiple of its alignment. The alignment of a `struct`, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields.

r[layout.aggregate.union-offsets] The fields of a `union` may have any offset within the `union`. In particular, `union` fields are permitted to overlap within the `union`.

> [!NOTE]
> Typically, union fields are all given offset 0 and are all allocated in the same storage. This is not necessarily guaranteed, however, for [The Rust Representation][layout.repr.rust]

r[layout.aggregate.union-size-align] The size of a `union` is at least such that the largest field, and the size is a multiple of the alignment. The alignment of a `union`, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields.
r[layout.aggregate.union-size-align] The size of a `union` is at least such that the largest field, and the size is a multiple of the alignment. The alignment of a `union`, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields.

r[layout.aggregate.repr] The [`repr`][layout.repr] attribute may restrict the valid offsets for each field, as well as the size and alignment of the aggregate type. By [default][layout.repr.rust], the offsets of fields are unspecified.

@@ -234,26 +234,26 @@ r[layout.repr.rust.intro]
The `Rust` representation is the default representation for nominal types
without a `repr` attribute. Using this representation explicitly through a
`repr` attribute is guaranteed to be the same as omitting the attribute
entirely.
entirely.

r[layout.repr.rust.aggregate] The layout of aggregate types with this repr is unspecified, such that the guarantees of all `struct` and `union` types are upheld.

> [!NOTE]
> [!NOTE]
> `repr(Rust)` does not provide any guarantees other than the default constraints.

#### `repr(Rust)` Enums

r[layout.repr.rust.enum]

r[layout.repr.rust.enum.intro] Like `struct`s and `union`s with the `Rust` representation, `enum`s typically have no guarantees. The fields of individual variants are layed out with the same rules as a `repr(Rust)` struct, and the `enum` contains sufficient information to determine which variant is being represented.
r[layout.repr.rust.enum.intro] Like `struct`s and `union`s with the `Rust` representation, `enum`s typically have no guarantees. The fields of individual variants are layed out with the same rules as a `repr(Rust)` struct, and the `enum` contains sufficient information to determine which variant is being represented.

r[layout.repr.rust.enum.variant-fields] Each field of a variant has an offset within the `enum`, such that no two fields of the same variant overlap, and each field of each variant is aligned, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute. Fields of different variants are allowed to overlap, as though each variant appears within a `union` definition.

r[layout.repr.rust.enum.size-align] The size of an enum is such that each field of each variant that is not uninhabited can be allocated within the enum at its given offset. The alignment of an enum, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields in variants that are inhabited.
r[layout.repr.rust.enum.size-align] The size of an enum is such that each field of each variant that is not uninhabited can be allocated within the enum at its given offset. The alignment of an enum, unless modified by the [`repr(packed)`][layout.repr.alignment.packed] attribute, is at least the largest alignment of all fields in variants that are inhabited.

> [!NOTE]
> A Rough approximation of a `repr(Rust)` enum is a `repr(Rust)` union containing `repr(Rust)` structs for each variant, with a discriminant field present in each struct.
> However, there is no guarantee that the discriminant field is any particular size, or exists within the union, nor stores any particular value.
> However, there is no guarantee that the discriminant field is any particular size, or exists within the union, nor stores any particular value.
> Several optimizations can also reduce the size of the `enum` beyond what is valid for a union-of-structs layout, even using the `Rust` representation.

> [!NOTE]
@@ -263,15 +263,15 @@ r[layout.repr.rust.enum.size-align] The size of an enum is such that each field

r[layout.repr.rust.option]

r[layout.repr.rust.option.intro] Certain `repr(Rust)` enums are specially layed out when used with certain types. This layout process is known as discriminant elision.
r[layout.repr.rust.option.intro] Certain `repr(Rust)` enums are specially layed out when used with certain types. This layout process is known as discriminant elision.

r[layout.repr.rust.option.elligible] An `enum` type is a *discriminant elision eligible* enum if:
* It has exactly two variants,
* One variant has exactly one field, known as the *elision candidate field*, and
* The other variant has no fields that have size greater than 0 or alignment greater than 1, known as the *elided variant*.

> [!NOTE]
> The determination of whether an `enum` type is *discriminant elision eligible* applies after mono-morphization.
> The determination of whether an `enum` type is *discriminant elision eligible* applies after mono-morphization.
> In particular, a type like [`core::result::Result<T,E>`] is *discriminant elision eligible* if either `T` or `E` is instantiated with a 1-ZST type, and [`core::option::Option<T>`] is *discriminant elision eligible* always (due to its `None` variant).

r[layout.repr.rust.option.candidates] The following types are *elision candidate types*:
@@ -307,8 +307,7 @@ is [zero-variant enums] for which the `C` representation is an error.

r[layout.repr.c.aggregate] An aggregate type (`struct` or `union`) with the `C` representation is laid out by each field being given by the smallest valid offset for that field that is ascending in declaration order. That is, for a `union`, each field is at offset `0`, and for a struct, the first field is at offset `0`, then the second is at the next offset aligned to the field type. The size of such an aggregate type is the minimum value valid for the type.


r[layout.repr.c.align] An aggregate type with the `C` representation has an alignment equal to the maximum alignment of each of its fields, unless an [alignment modifier][layout.repr.alignment] is present.
r[layout.repr.c.align] An aggregate type with the `C` representation has an alignment equal to the maximum alignment of each of its fields, unless an [alignment modifier][layout.repr.alignment] is present.

> [!NOTE]
> The layout of unions in particular is maximally compact - the size of a `C` representation `union` is the size of its largest field, rounded up to the alignment of the `union`
@@ -336,7 +335,6 @@ assert_eq!(std::mem::size_of::<SizeRoundedUp>(), 8); // Size of 6 from b,
assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
```


#### `#[repr(C)]` Structs

r[layout.repr.c.struct]