Skip to content

Commit 7ce3563

Browse files
authored
Merge pull request #1614 from chorman0773/spec-add-identifier-type-layout
Add identifier syntax to type-layout.md
2 parents 11ef652 + 179f3ac commit 7ce3563

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,9 +1,13 @@
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

@@ -13,22 +17,26 @@ see [here][fn-abi-compatibility].
1317

1418
## Size and Alignment
1519

20+
r[layout.properties]
1621
All values have an alignment and size.
1722

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

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

39+
r[layout.properties.sized]
3240
Types where all values have the same size and alignment, and both are known at
3341
compile time, implement the [`Sized`] trait and can be checked with the
3442
[`size_of`] and [`align_of`] functions. Types that are not [`Sized`] are known
@@ -38,6 +46,9 @@ the alignment of the type respectively.
3846

3947
## Primitive Data Layout
4048

49+
r[layout.primitive]
50+
51+
r[layout.primitive.size]
4152
The size of most primitives is given in this table.
4253

4354
| Type | `size_of::<Type>()`|
@@ -53,10 +64,12 @@ The size of most primitives is given in this table.
5364
| `f64` | 8 |
5465
| `char` | 4 |
5566

67+
r[layout.primitive.size-int]
5668
`usize` and `isize` have a size big enough to contain every address on the
5769
target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
5870
bit target, this is 8 bytes.
5971

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

6679
## Pointers and References Layout
6780

81+
r[layout.pointer]
82+
83+
r[layout.pointer.intro]
6884
Pointers and references have the same layout. Mutability of the pointer or
6985
reference does not change the layout.
7086

87+
r[layout.pointer.thin]
7188
Pointers to sized types have the same size and alignment as `usize`.
7289

90+
r[layout.pointer.unsized]
7391
Pointers to unsized types are sized. The size and alignment is guaranteed to be
7492
at least equal to the size and alignment of a pointer.
7593

@@ -79,49 +97,70 @@ at least equal to the size and alignment of a pointer.
7997
8098
## Array Layout
8199

100+
r[layout.array]
101+
82102
An array of `[T; N]` has a size of `size_of::<T>() * N` and the same alignment
83103
of `T`. Arrays are laid out so that the zero-based `nth` element of the array
84104
is offset from the start of the array by `n * size_of::<T>()` bytes.
85105

86106
## Slice Layout
87107

108+
r[layout.slice]
109+
88110
Slices have the same layout as the section of the array they slice.
89111

90112
> Note: This is about the raw `[T]` type, not pointers (`&[T]`, `Box<[T]>`,
91113
> etc.) to slices.
92114
93115
## `str` Layout
116+
117+
r[layout.str]
118+
94119
String slices are a UTF-8 representation of characters that have the same layout as slices of type `[u8]`.
95120

96121
## Tuple Layout
97122

123+
r[layout.tuple]
124+
125+
r[layout.tuple.general]
98126
Tuples are laid out according to the [`Rust` representation][`Rust`].
99127

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

103132
## Trait Object Layout
104133

134+
r[layout.trait-object]
135+
105136
Trait objects have the same layout as the value the trait object is of.
106137

107138
> Note: This is about the raw trait object types, not pointers (`&dyn Trait`,
108139
> `Box<dyn Trait>`, etc.) to trait objects.
109140
110141
## Closure Layout
111142

143+
r[layout.closure]
144+
112145
Closures have no layout guarantees.
113146

114147
## Representations
115148

149+
r[layout.repr]
150+
151+
r[layout.repr.intro]
116152
All user-defined composite types (`struct`s, `enum`s, and `union`s) have a
117-
*representation* that specifies what the layout is for the type. The possible
118-
representations for a type are:
153+
*representation* that specifies what the layout is for the type.
154+
155+
r[layout.repr.kinds]
156+
The possible representations for a type are:
119157

120158
- [`Rust`] (default)
121159
- [`C`]
122160
- The [primitive representations]
123161
- [`transparent`]
124162

163+
r[layout.repr.attribute]
125164
The representation of a type can be changed by applying the `repr` attribute
126165
to it. The following example shows a struct with a `C` representation.
127166

@@ -134,6 +173,7 @@ struct ThreeInts {
134173
}
135174
```
136175

176+
r[layout.repr.align-packed]
137177
The alignment may be raised or lowered with the `align` and `packed` modifiers
138178
respectively. They alter the representation specified in the attribute.
139179
If no representation is specified, the default one is altered.
@@ -161,27 +201,36 @@ struct AlignedStruct {
161201
> the same name have the same representation. For example, `Foo<Bar>` and
162202
> `Foo<Baz>` both have the same representation.
163203
204+
r[layout.repr.inter-field]
164205
The representation of a type can change the padding between fields, but does
165206
not change the layout of the fields themselves. For example, a struct with a
166207
`C` representation that contains a struct `Inner` with the default
167208
representation will not change the layout of `Inner`.
168209

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

212+
r[layout.repr.rust]
213+
214+
r[layout.repr.rust.intro]
171215
The `Rust` representation is the default representation for nominal types
172216
without a `repr` attribute. Using this representation explicitly through a
173217
`repr` attribute is guaranteed to be the same as omitting the attribute
174218
entirely.
175219

220+
r[layout.repr.rust.layout]
176221
The only data layout guarantees made by this representation are those required
177222
for soundness. They are:
178223

179224
1. The fields are properly aligned.
180225
2. The fields do not overlap.
181226
3. The alignment of the type is at least the maximum alignment of its fields.
182227

228+
r[layout.repr.rust.alignment]
183229
Formally, the first guarantee means that the offset of any field is divisible by
184-
that field's alignment. The second guarantee means that the fields can be
230+
that field's alignment.
231+
232+
r[layout.repr.rust.field-storage]
233+
The second guarantee means that the fields can be
185234
ordered such that the offset plus the size of any field is less than or equal to
186235
the offset of the next field in the ordering. The ordering does not have to be
187236
the same as the order in which the fields are specified in the declaration of
@@ -191,10 +240,14 @@ Be aware that the second guarantee does not imply that the fields have distinct
191240
addresses: zero-sized types may have the same address as other fields in the
192241
same struct.
193242

243+
r[layout.repr.rust.unspecified]
194244
There are no other guarantees of data layout made by this representation.
195245

196246
### The `C` Representation
197247

248+
r[layout.repr.c]
249+
250+
r[layout.repr.c.intro]
198251
The `C` representation is designed for dual purposes. One purpose is for
199252
creating types that are interoperable with the C Language. The second purpose is
200253
to create types that you can soundly perform operations on that rely on data
@@ -203,13 +256,18 @@ layout such as reinterpreting values as a different type.
203256
Because of this dual purpose, it is possible to create types that are not useful
204257
for interfacing with the C programming language.
205258

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

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

265+
r[layout.repr.c.struct]
266+
267+
r[layout.repr.c.struct.align]
211268
The alignment of the struct is the alignment of the most-aligned field in it.
212269

270+
r[layout.repr.c.struct.size-field-offset]
213271
The size and offset of fields is determined by the following algorithm.
214272

215273
Start with a current offset of 0 bytes.
@@ -270,8 +328,13 @@ struct.size = current_offset + padding_needed_for(current_offset, struct.alignme
270328
271329
#### `#[repr(C)]` Unions
272330

331+
r[layout.repr.c.union]
332+
333+
r[layout.repr.c.union.intro]
273334
A union declared with `#[repr(C)]` will have the same size and alignment as an
274335
equivalent C union declaration in the C language for the target platform.
336+
337+
r[layout.repr.c.union.size-align]
275338
The union will have a size of the maximum size of all of its fields rounded to
276339
its alignment, and an alignment of the maximum alignment of all of its fields.
277340
These maximums may come from different fields.
@@ -300,6 +363,8 @@ assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
300363

301364
#### `#[repr(C)]` Field-less Enums
302365

366+
r[layout.repr.c.enum]
367+
303368
For [field-less enums], the `C` representation has the size and alignment of
304369
the default `enum` size and alignment for the target platform's C ABI.
305370

@@ -312,10 +377,16 @@ the default `enum` size and alignment for the target platform's C ABI.
312377
313378
#### `#[repr(C)]` Enums With Fields
314379

380+
r[layout.repr.c.adt]
381+
382+
r[layout.repr.c.adt.intro]
315383
The representation of a `repr(C)` enum with fields is a `repr(C)` struct with
316384
two fields, also called a "tagged union" in C:
317385

386+
r[layout.repr.c.adt.tag]
318387
- a `repr(C)` version of the enum with all fields removed ("the tag")
388+
389+
r[layout.repr.c.adt.fields]
319390
- a `repr(C)` union of `repr(C)` structs for the fields of each variant that had
320391
them ("the payload")
321392

@@ -378,24 +449,32 @@ struct MyDFields;
378449
379450
### Primitive representations
380451

452+
r[layout.repr.primitive]
453+
454+
r[layout.repr.primitive.intro]
381455
The *primitive representations* are the representations with the same names as
382456
the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`,
383457
`usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`.
384458

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

390465
#### Primitive Representation of Field-less Enums
391466

467+
r[layout.repr.primitive.enum]
468+
392469
For [field-less enums], primitive representations set the size and alignment to
393470
be the same as the primitive type of the same name. For example, a field-less
394471
enum with a `u8` representation can only have discriminants between 0 and 255
395472
inclusive.
396473

397474
#### Primitive Representation of Enums With Fields
398475

476+
r[layout.repr.primitive.adt]
477+
399478
The representation of a primitive representation enum is a `repr(C)` union of
400479
`repr(C)` structs for each variant with a field. The first field of each struct
401480
in the union is the primitive representation version of the enum with all fields
@@ -450,6 +529,8 @@ struct MyVariantD(MyEnumDiscriminant);
450529
451530
#### Combining primitive representations of enums with fields and `#[repr(C)]`
452531

532+
r[layout.repr.primitive-c]
533+
453534
For enums with fields, it is also possible to combine `repr(C)` and a
454535
primitive representation (e.g., `repr(C, u8)`). This modifies the [`repr(C)`] by
455536
changing the representation of the discriminant enum to the chosen primitive
@@ -514,6 +595,9 @@ assert_eq!(std::mem::size_of::<Enum16>(), 4);
514595

515596
### The alignment modifiers
516597

598+
r[layout.repr.alignment]
599+
600+
r[layout.repr.alignment.intro]
517601
The `align` and `packed` modifiers can be used to respectively raise or lower
518602
the alignment of `struct`s and `union`s. `packed` may also alter the padding
519603
between fields (although it will not alter the padding inside of any field).
@@ -522,28 +606,37 @@ of fields in the layout of a struct or the layout of an enum variant, although
522606
they may be combined with representations (such as `C`) which do provide such
523607
guarantees.
524608

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

615+
r[layout.repr.alignment.align]
530616
For `align`, if the specified alignment is less than the alignment of the type
531617
without the `align` modifier, then the alignment is unaffected.
532618

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

634+
r[layout.repr.alignment.constraint-exclusive]
543635
The `align` and `packed` modifiers cannot be applied on the same type and a
544636
`packed` type cannot transitively contain another `align`ed type. `align` and
545637
`packed` may only be applied to the [`Rust`] and [`C`] representations.
546638

639+
r[layout.repr.alignment.enum]
547640
The `align` modifier can also be applied on an `enum`.
548641
When it is, the effect on the `enum`'s alignment is the same as if the `enum`
549642
was wrapped in a newtype `struct` with the same `align` modifier.
@@ -573,11 +666,15 @@ was wrapped in a newtype `struct` with the same `align` modifier.
573666
574667
### The `transparent` Representation
575668
669+
r[layout.repr.transparent]
670+
671+
r[layout.repr.transparent.constraint-field]
576672
The `transparent` representation can only be used on a [`struct`][structs]
577673
or an [`enum`][enumerations] with a single variant that has:
578674
- any number of fields with size 0 and alignment 1 (e.g. [`PhantomData<T>`]), and
579675
- at most one other field.
580676
677+
r[layout.repr.transparent.layout-abi]
581678
Structs and enums with this representation have the same layout and ABI
582679
as the only non-size 0 non-alignment 1 field, if present, or unit otherwise.
583680
@@ -586,6 +683,7 @@ a struct with the `C` representation will always have the ABI of a `C` `struct`
586683
while, for example, a struct with the `transparent` representation with a
587684
primitive field will have the ABI of the primitive field.
588685
686+
r[layout.repr.transparent.constraint-exclusive]
589687
Because this representation delegates type layout to another type, it cannot be
590688
used with any other representation.
591689

0 commit comments

Comments
 (0)