Skip to content

Commit a3bd1fd

Browse files
committed
Add identifier syntax to type-layout.md
1 parent 687faf9 commit a3bd1fd

File tree

1 file changed

+101
-3
lines changed

1 file changed

+101
-3
lines changed

src/type-layout.md

+101-3
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
# Type Layout
22

3+
r[layout]
4+
5+
r[layout.intro]
36
The layout of a type is its size, alignment, and the relative offsets of its
47
fields. For enums, how the discriminant is laid out and interpreted is also part
58
of type layout.
69

10+
r[layout.guarantees]
711
Type layout can be changed with each compilation. Instead of trying to document
812
exactly what is done, we only document what is guaranteed today.
913

1014
## Size and Alignment
1115

16+
r[layout.properties]
1217
All values have an alignment and size.
1318

19+
r[layout.properties.align]
1420
The *alignment* of a value specifies what addresses are valid to store the value
1521
at. A value of alignment `n` must only be stored at an address that is a
1622
multiple of n. For example, a value with an alignment of 2 must be stored at an
1723
even address, while a value with an alignment of 1 can be stored at any address.
1824
Alignment is measured in bytes, and must be at least 1, and always a power of 2.
1925
The alignment of a value can be checked with the [`align_of_val`] function.
2026

27+
r[layout.properties.size]
2128
The *size* of a value is the offset in bytes between successive elements in an
2229
array with that item type including alignment padding. The size of a value is
2330
always a multiple of its alignment. Note that some types are zero-sized; 0 is
2431
considered a multiple of any alignment (for example, on some platforms, the type
2532
`[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with
2633
the [`size_of_val`] function.
2734

35+
r[layout.properties.sized]
2836
Types where all values have the same size and alignment, and both are known at
2937
compile time, implement the [`Sized`] trait and can be checked with the
3038
[`size_of`] and [`align_of`] functions. Types that are not [`Sized`] are known
@@ -34,6 +42,9 @@ the alignment of the type respectively.
3442

3543
## Primitive Data Layout
3644

45+
r[layout.primitive]
46+
47+
r[layout.primitive.size]
3748
The size of most primitives is given in this table.
3849

3950
| Type | `size_of::<Type>()`|
@@ -49,10 +60,12 @@ The size of most primitives is given in this table.
4960
| `f64` | 8 |
5061
| `char` | 4 |
5162

63+
r[layout.primitive.size-int]
5264
`usize` and `isize` have a size big enough to contain every address on the
5365
target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
5466
bit target, this is 8 bytes.
5567

68+
r[layout.primitive.align]
5669
The alignment of primitives is platform-specific.
5770
In most cases, their alignment is equal to their size, but it may be less.
5871
In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though
@@ -61,11 +74,16 @@ aligned to 4 bytes, not 8.
6174

6275
## Pointers and References Layout
6376

77+
r[layout.pointer]
78+
79+
r[layout.pointer.intro]
6480
Pointers and references have the same layout. Mutability of the pointer or
6581
reference does not change the layout.
6682

83+
r[layout.pointer.thin]
6784
Pointers to sized types have the same size and alignment as `usize`.
6885

86+
r[layout.pointer.unsized]
6987
Pointers to unsized types are sized. The size and alignment is guaranteed to be
7088
at least equal to the size and alignment of a pointer.
7189

@@ -75,49 +93,70 @@ at least equal to the size and alignment of a pointer.
7593
7694
## Array Layout
7795

96+
r[layout.array]
97+
7898
An array of `[T; N]` has a size of `size_of::<T>() * N` and the same alignment
7999
of `T`. Arrays are laid out so that the zero-based `nth` element of the array
80100
is offset from the start of the array by `n * size_of::<T>()` bytes.
81101

82102
## Slice Layout
83103

104+
r[layout.slice]
105+
84106
Slices have the same layout as the section of the array they slice.
85107

86108
> Note: This is about the raw `[T]` type, not pointers (`&[T]`, `Box<[T]>`,
87109
> etc.) to slices.
88110
89111
## `str` Layout
112+
113+
r[layout.str]
114+
90115
String slices are a UTF-8 representation of characters that have the same layout as slices of type `[u8]`.
91116

92117
## Tuple Layout
93118

119+
r[layout.tuple]
120+
121+
r[layout.tuple.general]
94122
Tuples are laid out according to the [`Rust` representation][`Rust`].
95123

124+
r[layout.tuple.unit]
96125
The exception to this is the unit tuple (`()`), which is guaranteed as a
97126
zero-sized type to have a size of 0 and an alignment of 1.
98127

99128
## Trait Object Layout
100129

130+
r[layout.trait-object]
131+
101132
Trait objects have the same layout as the value the trait object is of.
102133

103134
> Note: This is about the raw trait object types, not pointers (`&dyn Trait`,
104135
> `Box<dyn Trait>`, etc.) to trait objects.
105136
106137
## Closure Layout
107138

139+
r[kayout.closure]
140+
108141
Closures have no layout guarantees.
109142

110143
## Representations
111144

145+
r[layout.repr]
146+
147+
r[layout.repr.intro]
112148
All user-defined composite types (`struct`s, `enum`s, and `union`s) have a
113-
*representation* that specifies what the layout is for the type. The possible
114-
representations for a type are:
149+
*representation* that specifies what the layout is for the type.
150+
151+
r[layout.repr.kinds]
152+
The possible representations for a type are:
115153

116154
- [`Rust`] (default)
117155
- [`C`]
118156
- The [primitive representations]
119157
- [`transparent`]
120158

159+
r[layout.repr.attribute]
121160
The representation of a type can be changed by applying the `repr` attribute
122161
to it. The following example shows a struct with a `C` representation.
123162

@@ -130,6 +169,7 @@ struct ThreeInts {
130169
}
131170
```
132171

172+
r[layout.repr.align-packed]
133173
The alignment may be raised or lowered with the `align` and `packed` modifiers
134174
respectively. They alter the representation specified in the attribute.
135175
If no representation is specified, the default one is altered.
@@ -157,27 +197,36 @@ struct AlignedStruct {
157197
> the same name have the same representation. For example, `Foo<Bar>` and
158198
> `Foo<Baz>` both have the same representation.
159199
200+
r[layout.repr.inter-field]
160201
The representation of a type can change the padding between fields, but does
161202
not change the layout of the fields themselves. For example, a struct with a
162203
`C` representation that contains a struct `Inner` with the default
163204
representation will not change the layout of `Inner`.
164205

165206
### <a id="the-default-representation"></a> The `Rust` Representation
166207

208+
r[layout.repr.rust]
209+
210+
r[layout.repr.rust.intro]
167211
The `Rust` representation is the default representation for nominal types
168212
without a `repr` attribute. Using this representation explicitly through a
169213
`repr` attribute is guaranteed to be the same as omitting the attribute
170214
entirely.
171215

216+
r[layout.repr.rust.layout]
172217
The only data layout guarantees made by this representation are those required
173218
for soundness. They are:
174219

175220
1. The fields are properly aligned.
176221
2. The fields do not overlap.
177222
3. The alignment of the type is at least the maximum alignment of its fields.
178223

224+
r[layout.repr.rust.alignment]
179225
Formally, the first guarantee means that the offset of any field is divisible by
180-
that field's alignment. The second guarantee means that the fields can be
226+
that field's alignment.
227+
228+
r[layout.repr.rust.field-storage]
229+
The second guarantee means that the fields can be
181230
ordered such that the offset plus the size of any field is less than or equal to
182231
the offset of the next field in the ordering. The ordering does not have to be
183232
the same as the order in which the fields are specified in the declaration of
@@ -187,10 +236,14 @@ Be aware that the second guarantee does not imply that the fields have distinct
187236
addresses: zero-sized types may have the same address as other fields in the
188237
same struct.
189238

239+
r[layout.repr.rust.unspecified]
190240
There are no other guarantees of data layout made by this representation.
191241

192242
### The `C` Representation
193243

244+
r[layout.repr.c]
245+
246+
r[layout.repr.c.intro]
194247
The `C` representation is designed for dual purposes. One purpose is for
195248
creating types that are interoperable with the C Language. The second purpose is
196249
to create types that you can soundly perform operations on that rely on data
@@ -199,13 +252,18 @@ layout such as reinterpreting values as a different type.
199252
Because of this dual purpose, it is possible to create types that are not useful
200253
for interfacing with the C programming language.
201254

255+
r[layout.repr.c.constraint]
202256
This representation can be applied to structs, unions, and enums. The exception
203257
is [zero-variant enums] for which the `C` representation is an error.
204258

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

261+
r[layout.repr.c.struct]
262+
263+
r[layour.repr.c.struct.align]
207264
The alignment of the struct is the alignment of the most-aligned field in it.
208265

266+
r[layout.repr.c.struct.size-field-offset]
209267
The size and offset of fields is determined by the following algorithm.
210268

211269
Start with a current offset of 0 bytes.
@@ -266,8 +324,13 @@ struct.size = current_offset + padding_needed_for(current_offset, struct.alignme
266324
267325
#### `#[repr(C)]` Unions
268326

327+
r[layout.repr.c.union]
328+
329+
r[layout.repr.c.union.intro]
269330
A union declared with `#[repr(C)]` will have the same size and alignment as an
270331
equivalent C union declaration in the C language for the target platform.
332+
333+
r[layout.repr.c.union.size-align]
271334
The union will have a size of the maximum size of all of its fields rounded to
272335
its alignment, and an alignment of the maximum alignment of all of its fields.
273336
These maximums may come from different fields.
@@ -296,6 +359,8 @@ assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
296359

297360
#### `#[repr(C)]` Field-less Enums
298361

362+
r[layout.repr.c.enum]
363+
299364
For [field-less enums], the `C` representation has the size and alignment of
300365
the default `enum` size and alignment for the target platform's C ABI.
301366

@@ -308,10 +373,16 @@ the default `enum` size and alignment for the target platform's C ABI.
308373
309374
#### `#[repr(C)]` Enums With Fields
310375

376+
r[layout.repr.c.adt]
377+
378+
r[layout.repr.c.adt.intro]
311379
The representation of a `repr(C)` enum with fields is a `repr(C)` struct with
312380
two fields, also called a "tagged union" in C:
313381

382+
r[layout.repr.c.adt.tag]
314383
- a `repr(C)` version of the enum with all fields removed ("the tag")
384+
385+
r[layout.repr.c.adt.fields]
315386
- a `repr(C)` union of `repr(C)` structs for the fields of each variant that had
316387
them ("the payload")
317388

@@ -374,24 +445,32 @@ struct MyDFields;
374445
375446
### Primitive representations
376447

448+
r[layout.repr.primitive]
449+
450+
r[layout.repr.primitive.intro]
377451
The *primitive representations* are the representations with the same names as
378452
the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`,
379453
`usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`.
380454

455+
r[layout.repr.primitive.constraint]
381456
Primitive representations can only be applied to enumerations and have
382457
different behavior whether the enum has fields or no fields. It is an error
383458
for [zero-variant enums] to have a primitive representation. Combining
384459
two primitive representations together is an error.
385460

386461
#### Primitive Representation of Field-less Enums
387462

463+
r[layout.repr.primitive.enum]
464+
388465
For [field-less enums], primitive representations set the size and alignment to
389466
be the same as the primitive type of the same name. For example, a field-less
390467
enum with a `u8` representation can only have discriminants between 0 and 255
391468
inclusive.
392469

393470
#### Primitive Representation of Enums With Fields
394471

472+
r[layout.repr.primitive.adt]
473+
395474
The representation of a primitive representation enum is a `repr(C)` union of
396475
`repr(C)` structs for each variant with a field. The first field of each struct
397476
in the union is the primitive representation version of the enum with all fields
@@ -446,6 +525,8 @@ struct MyVariantD(MyEnumDiscriminant);
446525
447526
#### Combining primitive representations of enums with fields and `#[repr(C)]`
448527

528+
r[layout.repr.primitive-c]
529+
449530
For enums with fields, it is also possible to combine `repr(C)` and a
450531
primitive representation (e.g., `repr(C, u8)`). This modifies the [`repr(C)`] by
451532
changing the representation of the discriminant enum to the chosen primitive
@@ -510,6 +591,9 @@ assert_eq!(std::mem::size_of::<Enum16>(), 4);
510591

511592
### The alignment modifiers
512593

594+
r[layout.repr.alignment]
595+
596+
r[layout.repr.alignment.intro]
513597
The `align` and `packed` modifiers can be used to respectively raise or lower
514598
the alignment of `struct`s and `union`s. `packed` may also alter the padding
515599
between fields (although it will not alter the padding inside of any field).
@@ -518,28 +602,37 @@ of fields in the layout of a struct or the layout of an enum variant, although
518602
they may be combined with representations (such as `C`) which do provide such
519603
guarantees.
520604

605+
r[layout.repr.alignment.constraint-alignment]
521606
The alignment is specified as an integer parameter in the form of
522607
`#[repr(align(x))]` or `#[repr(packed(x))]`. The alignment value must be a
523608
power of two from 1 up to 2<sup>29</sup>. For `packed`, if no value is given,
524609
as in `#[repr(packed)]`, then the value is 1.
525610

611+
r[layout.repr.alignment.align]
526612
For `align`, if the specified alignment is less than the alignment of the type
527613
without the `align` modifier, then the alignment is unaffected.
528614

615+
r[layout.repr.alignment.packed]
529616
For `packed`, if the specified alignment is greater than the type's alignment
530617
without the `packed` modifier, then the alignment and layout is unaffected.
618+
619+
r[layout.repr.alignment.packed-fields]
531620
The alignments of each field, for the purpose of positioning fields, is the
532621
smaller of the specified alignment and the alignment of the field's type.
622+
623+
r[layout.repr.alignment.packed-padding]
533624
Inter-field padding is guaranteed to be the minimum required in order to
534625
satisfy each field's (possibly altered) alignment (although note that, on its
535626
own, `packed` does not provide any guarantee about field ordering). An
536627
important consequence of these rules is that a type with `#[repr(packed(1))]`
537628
(or `#[repr(packed)]`) will have no inter-field padding.
538629

630+
r[layout.repr.alignment.constraint-exclusive]
539631
The `align` and `packed` modifiers cannot be applied on the same type and a
540632
`packed` type cannot transitively contain another `align`ed type. `align` and
541633
`packed` may only be applied to the [`Rust`] and [`C`] representations.
542634

635+
r[layout.repr.alignment.enum]
543636
The `align` modifier can also be applied on an `enum`.
544637
When it is, the effect on the `enum`'s alignment is the same as if the `enum`
545638
was wrapped in a newtype `struct` with the same `align` modifier.
@@ -569,11 +662,15 @@ was wrapped in a newtype `struct` with the same `align` modifier.
569662
570663
### The `transparent` Representation
571664
665+
r[layout.repr.transparent]
666+
667+
r[layout.repr.transparent.constraint-field]
572668
The `transparent` representation can only be used on a [`struct`][structs]
573669
or an [`enum`][enumerations] with a single variant that has:
574670
- any number of fields with size 0 and alignment 1 (e.g. [`PhantomData<T>`]), and
575671
- at most one other field.
576672
673+
r[layout.repr.transparent.layout-abi]
577674
Structs and enums with this representation have the same layout and ABI
578675
as the only non-size 0 non-alignment 1 field, if present, or unit otherwise.
579676
@@ -582,6 +679,7 @@ a struct with the `C` representation will always have the ABI of a `C` `struct`
582679
while, for example, a struct with the `transparent` representation with a
583680
primitive field will have the ABI of the primitive field.
584681
682+
r[layout.repr.transparent.constraint-exclusive]
585683
Because this representation delegates type layout to another type, it cannot be
586684
used with any other representation.
587685

0 commit comments

Comments
 (0)