Skip to content

Commit 1015d13

Browse files
committed
Add repr attribute template, and add combination rules
This consolidates the rules for how repr values can be combined. This adds a few previously undocumented combinations, and I think all permutations should now be covered.
1 parent df72aa4 commit 1015d13

File tree

1 file changed

+91
-12
lines changed

1 file changed

+91
-12
lines changed

src/type-layout.md

Lines changed: 91 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,78 @@ The *`repr` [attribute][attributes]* can change the representation and layout of
138138
> [!NOTE]
139139
> As a consequence of the representation being an attribute on the item, the representation does not depend on generic parameters. Any two types with the same name have the same representation. For example, `Foo<Bar>` and `Foo<Baz>` both have the same representation.
140140
141+
r[layout.repr.attribute.syntax]
142+
The syntax for the `repr` attribute is:
143+
144+
```grammar,attributes
145+
@root ReprAttribute -> `repr` `(` ( Repr (`,` Repr)* `,`? )? `)`
146+
147+
Repr ->
148+
`Rust`
149+
| `C`
150+
| `transparent`
151+
| `i8`
152+
| `u8`
153+
| `i16`
154+
| `u16`
155+
| `i32`
156+
| `u32`
157+
| `i64`
158+
| `u64`
159+
| `i128`
160+
| `u128`
161+
| `isize`
162+
| `usize`
163+
| `align` `(` Alignment `)`
164+
| `packed` ( `(` Alignment `)` )?
165+
166+
Alignment -> DEC_LITERAL | BIN_LITERAL | OCT_LITERAL | HEX_LITERAL
167+
```
168+
169+
The values of the `repr` attribute are described in the following sections:
170+
171+
- `Rust` --- [layout.repr.rust]
172+
- `C` --- [layout.repr.c]
173+
- `transparent` --- [layout.repr.transparent]
174+
- Primitive representations --- [layout.repr.primitive]
175+
- `align` and `packed` modifiers --- [layout.repr.alignment]
141176

177+
If multiple values are specified, then the combination of all the specified representations is used as specified in [layout.repr.attribute.combinations].
142178

179+
r[layout.repr.attribute.allowed-positions]
180+
The `repr` attribute may only be applied to a [struct], [enum], or [union].
181+
182+
> [!NOTE]
183+
> There are some restrictions on which `repr` values can be applied to specific kinds of items. For example, the primitive representations can only be applied to enumerations. The sections for each repr value describes their restrictions.
184+
185+
r[layout.repr.attribute.duplicates]
186+
If the `repr` attribute is specified multiple times on an item, then the combination of all the specified values is used as specified in [layout.repr.attribute.combinations].
187+
188+
r[layout.repr.attribute.combinations]
189+
Combinations of `repr` values on the same type are handled as follows:
190+
191+
r[layout.repr.attribute.combinations.transparent]
192+
- `transparent` --- May not be combined with any other value.
193+
r[layout.repr.attribute.combinations.rust]
194+
- `Rust` --- May not be combined with primitive representations or `C`.
195+
r[layout.repr.attribute.combinations.primitive]
196+
- Multiple primitive representations are not allowed.
197+
<!-- Note: Currently a future-compatible warning. -->
198+
r[layout.repr.attribute.combinations.primitive-c]
199+
- A primitive representation with `C` is described in [layout.repr.primitive-c].
200+
r[layout.repr.attribute.combinations.primitive-unit-only]
201+
- A primitive representation with `C` on a [unit-only enum] is not allowed.
202+
<!-- Note: Currently a future-compatible warning. -->
203+
r[layout.repr.attribute.combinations.align-packed]
204+
- `align` and `packed` may not be applied on the same type.
205+
r[layout.repr.attribute.combinations.align-packed-rust-or-c]
206+
- `align` and `packed` may only be applied to a type with the `Rust` or `C` representation.
207+
r[layout.repr.attribute.combinations.align-max]
208+
- If multiple align values are given, the maximum value is used.
209+
r[layout.repr.attribute.combinations.packed-min]
210+
- If multiple packed values are given, the minimum value is used.
211+
r[layout.repr.attribute.combinations.rust-c-dupe]
212+
- Duplicate instances of the `Rust` or `C` value are ignored.
143213

144214
r[layout.repr.inter-field]
145215
The representation of a type can change the padding between fields, but does not change the layout of the fields themselves. For example, a struct with a `C` representation that contains a struct `Inner` with the `Rust` representation will not change the layout of `Inner`.
@@ -351,10 +421,13 @@ r[layout.repr.primitive]
351421
### Primitive representations
352422

353423
r[layout.repr.primitive.intro]
354-
The *primitive representations* are the representations with the same names as the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`.
424+
The *primitive representations* are used to change the representation of an enumeration. They have the same names as the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`.
355425

356-
r[layout.repr.primitive.constraint]
357-
Primitive representations can only be applied to enumerations and have different behavior whether the enum has fields or no fields. It is an error for [zero-variant enums] to have a primitive representation. Combining two primitive representations together is an error.
426+
r[layout.repr.primitive.enum-only]
427+
Primitive representations can only be applied to enumerations and have different behavior whether the enum has fields or no fields.
428+
429+
r[layout.repr.primitive.zero-variant]
430+
It is an error for [zero-variant enums] to have a primitive representation.
358431

359432
r[layout.repr.primitive.enum]
360433
#### Primitive Representation of Field-less Enums
@@ -475,7 +548,9 @@ r[layout.repr.alignment]
475548
### The alignment modifiers
476549

477550
r[layout.repr.alignment.intro]
478-
The `align` and `packed` modifiers can be used to respectively raise or lower the alignment of `struct`s and `union`s. `packed` may also alter the padding between fields (although it will not alter the padding inside of any field). On their own, `align` and `packed` do not provide guarantees about the order of fields in the layout of a struct or the layout of an enum variant, although they may be combined with representations (such as `C`) which do provide such guarantees.
551+
The `align` and `packed` modifiers can be used to respectively raise or lower the alignment of `struct`s and `union`s. `packed` may also alter the padding between fields (although it will not alter the padding inside of any field).
552+
553+
On their own, `align` and `packed` do not provide guarantees about the order of fields in the layout of a struct or the layout of an enum variant, although they may be combined with representations (such as `C`) which do provide such guarantees.
479554

480555
> [!EXAMPLE]
481556
> ```rust
@@ -511,11 +586,14 @@ The alignments of each field, for the purpose of positioning fields, is the smal
511586
r[layout.repr.alignment.packed-padding]
512587
Inter-field padding is guaranteed to be the minimum required in order to satisfy each field's (possibly altered) alignment (although note that, on its own, `packed` does not provide any guarantee about field ordering). An important consequence of these rules is that a type with `#[repr(packed(1))]` (or `#[repr(packed)]`) will have no inter-field padding.
513588
514-
r[layout.repr.alignment.constraint-exclusive]
515-
The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and `packed` may only be applied to the [`Rust`] and [`C`] representations.
589+
r[layout.repr.alignment.pack-transitive-aligned]
590+
A `packed` type may not transitively contain another `align`ed type.
516591
517-
r[layout.repr.alignment.enum]
518-
The `align` modifier can also be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` was wrapped in a newtype `struct` with the same `align` modifier.
592+
r[layout.repr.alignment.packed-enum]
593+
The `packed` modifier may not be used on an `enum`.
594+
595+
r[layout.repr.alignment.align-enum]
596+
The `align` modifier may be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` was wrapped in a newtype `struct` with the same `align` modifier.
519597
520598
> [!NOTE]
521599
> References to unaligned fields are not allowed because it is [undefined behavior]. When fields are unaligned due to an alignment modifier, consider the following options for using references and dereferences:
@@ -544,7 +622,7 @@ r[layout.repr.transparent]
544622
### The `transparent` Representation
545623
546624
r[layout.repr.transparent.constraint-field]
547-
The `transparent` representation can only be used on a [`struct`][structs] or an [`enum`][enumerations] with a single variant that has:
625+
The `transparent` representation may only be used on a [`struct`][structs] or an [`enum`][enumerations] with a single variant that has:
548626
549627
- any number of fields with size 0 and alignment 1 (e.g. [`PhantomData<T>`]), and
550628
- at most one other field.
@@ -554,9 +632,6 @@ Structs and enums with this representation have the same layout and ABI as the o
554632
555633
This is different than the `C` representation because a struct with the `C` representation will always have the ABI of a `C` `struct` while, for example, a struct with the `transparent` representation with a primitive field will have the ABI of the primitive field.
556634
557-
r[layout.repr.transparent.constraint-exclusive]
558-
Because this representation delegates type layout to another type, it cannot be used with any other representation.
559-
560635
[`align_of_val`]: std::mem::align_of_val
561636
[`size_of_val`]: std::mem::size_of_val
562637
[`align_of`]: std::mem::align_of
@@ -577,3 +652,7 @@ Because this representation delegates type layout to another type, it cannot be
577652
[structs]: items/structs.md
578653
[`transparent`]: #the-transparent-representation
579654
[`Layout`]: std::alloc::Layout
655+
[struct]: items/structs.md
656+
[enum]: items/enumerations.md
657+
[union]: items/unions.md
658+
[unit-only enum]: items/enumerations.md#unit-only-enum

0 commit comments

Comments
 (0)