1
1
# Type Layout
2
2
3
+ r[ layout]
4
+
5
+ r[ layout.intro]
3
6
The layout of a type is its size, alignment, and the relative offsets of its
4
7
fields. For enums, how the discriminant is laid out and interpreted is also part
5
8
of type layout.
6
9
10
+ r[ layout.guarantees]
7
11
Type layout can be changed with each compilation. Instead of trying to document
8
12
exactly what is done, we only document what is guaranteed today.
9
13
10
14
## Size and Alignment
11
15
16
+ r[ layout.properties]
12
17
All values have an alignment and size.
13
18
19
+ r[ layout.properties.align]
14
20
The * alignment* of a value specifies what addresses are valid to store the value
15
21
at. A value of alignment ` n ` must only be stored at an address that is a
16
22
multiple of n. For example, a value with an alignment of 2 must be stored at an
17
23
even address, while a value with an alignment of 1 can be stored at any address.
18
24
Alignment is measured in bytes, and must be at least 1, and always a power of 2.
19
25
The alignment of a value can be checked with the [ ` align_of_val ` ] function.
20
26
27
+ r[ layout.properties.size]
21
28
The * size* of a value is the offset in bytes between successive elements in an
22
29
array with that item type including alignment padding. The size of a value is
23
30
always a multiple of its alignment. Note that some types are zero-sized; 0 is
24
31
considered a multiple of any alignment (for example, on some platforms, the type
25
32
` [u16; 0] ` has size 0 and alignment 2). The size of a value can be checked with
26
33
the [ ` size_of_val ` ] function.
27
34
35
+ r[ layout.properties.sized]
28
36
Types where all values have the same size and alignment, and both are known at
29
37
compile time, implement the [ ` Sized ` ] trait and can be checked with the
30
38
[ ` size_of ` ] and [ ` align_of ` ] functions. Types that are not [ ` Sized ` ] are known
@@ -34,6 +42,9 @@ the alignment of the type respectively.
34
42
35
43
## Primitive Data Layout
36
44
45
+ r[ layout.primitive]
46
+
47
+ r[ layout.primitive.size]
37
48
The size of most primitives is given in this table.
38
49
39
50
| Type | ` size_of::<Type>() ` |
@@ -49,10 +60,12 @@ The size of most primitives is given in this table.
49
60
| ` f64 ` | 8 |
50
61
| ` char ` | 4 |
51
62
63
+ r[ layout.primitive.size-int]
52
64
` usize ` and ` isize ` have a size big enough to contain every address on the
53
65
target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
54
66
bit target, this is 8 bytes.
55
67
68
+ r[ layout.primitive.align]
56
69
The alignment of primitives is platform-specific.
57
70
In most cases, their alignment is equal to their size, but it may be less.
58
71
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.
61
74
62
75
## Pointers and References Layout
63
76
77
+ r[ layout.pointer]
78
+
79
+ r[ layout.pointer.intro]
64
80
Pointers and references have the same layout. Mutability of the pointer or
65
81
reference does not change the layout.
66
82
83
+ r[ layout.pointer.thin]
67
84
Pointers to sized types have the same size and alignment as ` usize ` .
68
85
86
+ r[ layout.pointer.unsized]
69
87
Pointers to unsized types are sized. The size and alignment is guaranteed to be
70
88
at least equal to the size and alignment of a pointer.
71
89
@@ -75,49 +93,70 @@ at least equal to the size and alignment of a pointer.
75
93
76
94
## Array Layout
77
95
96
+ r[ layout.array]
97
+
78
98
An array of ` [T; N] ` has a size of ` size_of::<T>() * N ` and the same alignment
79
99
of ` T ` . Arrays are laid out so that the zero-based ` nth ` element of the array
80
100
is offset from the start of the array by ` n * size_of::<T>() ` bytes.
81
101
82
102
## Slice Layout
83
103
104
+ r[ layout.slice]
105
+
84
106
Slices have the same layout as the section of the array they slice.
85
107
86
108
> Note: This is about the raw ` [T] ` type, not pointers (` &[T] ` , ` Box<[T]> ` ,
87
109
> etc.) to slices.
88
110
89
111
## ` str ` Layout
112
+
113
+ r[ layout.str]
114
+
90
115
String slices are a UTF-8 representation of characters that have the same layout as slices of type ` [u8] ` .
91
116
92
117
## Tuple Layout
93
118
119
+ r[ layout.tuple]
120
+
121
+ r[ layout.tuple.general]
94
122
Tuples are laid out according to the [ ` Rust ` representation] [ `Rust` ] .
95
123
124
+ r[ layout.tuple.unit]
96
125
The exception to this is the unit tuple (` () ` ), which is guaranteed as a
97
126
zero-sized type to have a size of 0 and an alignment of 1.
98
127
99
128
## Trait Object Layout
100
129
130
+ r[ layout.trait-object]
131
+
101
132
Trait objects have the same layout as the value the trait object is of.
102
133
103
134
> Note: This is about the raw trait object types, not pointers (` &dyn Trait ` ,
104
135
> ` Box<dyn Trait> ` , etc.) to trait objects.
105
136
106
137
## Closure Layout
107
138
139
+ r[ kayout.closure]
140
+
108
141
Closures have no layout guarantees.
109
142
110
143
## Representations
111
144
145
+ r[ layout.repr]
146
+
147
+ r[ layout.repr.intro]
112
148
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:
115
153
116
154
- [ ` Rust ` ] (default)
117
155
- [ ` C ` ]
118
156
- The [ primitive representations]
119
157
- [ ` transparent ` ]
120
158
159
+ r[ layout.repr.attribute]
121
160
The representation of a type can be changed by applying the ` repr ` attribute
122
161
to it. The following example shows a struct with a ` C ` representation.
123
162
@@ -130,6 +169,7 @@ struct ThreeInts {
130
169
}
131
170
```
132
171
172
+ r[ layout.repr.align-packed]
133
173
The alignment may be raised or lowered with the ` align ` and ` packed ` modifiers
134
174
respectively. They alter the representation specified in the attribute.
135
175
If no representation is specified, the default one is altered.
@@ -157,27 +197,36 @@ struct AlignedStruct {
157
197
> the same name have the same representation. For example, ` Foo<Bar> ` and
158
198
> ` Foo<Baz> ` both have the same representation.
159
199
200
+ r[ layout.repr.inter-field]
160
201
The representation of a type can change the padding between fields, but does
161
202
not change the layout of the fields themselves. For example, a struct with a
162
203
` C ` representation that contains a struct ` Inner ` with the default
163
204
representation will not change the layout of ` Inner ` .
164
205
165
206
### <a id =" the-default-representation " ></a > The ` Rust ` Representation
166
207
208
+ r[ layout.repr.rust]
209
+
210
+ r[ layout.repr.rust.intro]
167
211
The ` Rust ` representation is the default representation for nominal types
168
212
without a ` repr ` attribute. Using this representation explicitly through a
169
213
` repr ` attribute is guaranteed to be the same as omitting the attribute
170
214
entirely.
171
215
216
+ r[ layout.repr.rust.layout]
172
217
The only data layout guarantees made by this representation are those required
173
218
for soundness. They are:
174
219
175
220
1 . The fields are properly aligned.
176
221
2 . The fields do not overlap.
177
222
3 . The alignment of the type is at least the maximum alignment of its fields.
178
223
224
+ r[ layout.repr.rust.alignment]
179
225
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
181
230
ordered such that the offset plus the size of any field is less than or equal to
182
231
the offset of the next field in the ordering. The ordering does not have to be
183
232
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
187
236
addresses: zero-sized types may have the same address as other fields in the
188
237
same struct.
189
238
239
+ r[ layout.repr.rust.unspecified]
190
240
There are no other guarantees of data layout made by this representation.
191
241
192
242
### The ` C ` Representation
193
243
244
+ r[ layout.repr.c]
245
+
246
+ r[ layout.repr.c.intro]
194
247
The ` C ` representation is designed for dual purposes. One purpose is for
195
248
creating types that are interoperable with the C Language. The second purpose is
196
249
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.
199
252
Because of this dual purpose, it is possible to create types that are not useful
200
253
for interfacing with the C programming language.
201
254
255
+ r[ layout.repr.c.constraint]
202
256
This representation can be applied to structs, unions, and enums. The exception
203
257
is [ zero-variant enums] for which the ` C ` representation is an error.
204
258
205
259
#### ` #[repr(C)] ` Structs
206
260
261
+ r[ layout.repr.c.struct]
262
+
263
+ r[ layour.repr.c.struct.align]
207
264
The alignment of the struct is the alignment of the most-aligned field in it.
208
265
266
+ r[ layout.repr.c.struct.size-field-offset]
209
267
The size and offset of fields is determined by the following algorithm.
210
268
211
269
Start with a current offset of 0 bytes.
@@ -266,8 +324,13 @@ struct.size = current_offset + padding_needed_for(current_offset, struct.alignme
266
324
267
325
#### ` #[repr(C)] ` Unions
268
326
327
+ r[ layout.repr.c.union]
328
+
329
+ r[ layout.repr.c.union.intro]
269
330
A union declared with ` #[repr(C)] ` will have the same size and alignment as an
270
331
equivalent C union declaration in the C language for the target platform.
332
+
333
+ r[ layout.repr.c.union.size-align]
271
334
The union will have a size of the maximum size of all of its fields rounded to
272
335
its alignment, and an alignment of the maximum alignment of all of its fields.
273
336
These maximums may come from different fields.
@@ -296,6 +359,8 @@ assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
296
359
297
360
#### ` #[repr(C)] ` Field-less Enums
298
361
362
+ r[ layout.repr.c.enum]
363
+
299
364
For [ field-less enums] , the ` C ` representation has the size and alignment of
300
365
the default ` enum ` size and alignment for the target platform's C ABI.
301
366
@@ -308,10 +373,16 @@ the default `enum` size and alignment for the target platform's C ABI.
308
373
309
374
#### ` #[repr(C)] ` Enums With Fields
310
375
376
+ r[ layout.repr.c.adt]
377
+
378
+ r[ layout.repr.c.adt.intro]
311
379
The representation of a ` repr(C) ` enum with fields is a ` repr(C) ` struct with
312
380
two fields, also called a "tagged union" in C:
313
381
382
+ r[ layout.repr.c.adt.tag]
314
383
- a ` repr(C) ` version of the enum with all fields removed ("the tag")
384
+
385
+ r[ layout.repr.c.adt.fields]
315
386
- a ` repr(C) ` union of ` repr(C) ` structs for the fields of each variant that had
316
387
them ("the payload")
317
388
@@ -374,24 +445,32 @@ struct MyDFields;
374
445
375
446
### Primitive representations
376
447
448
+ r[ layout.repr.primitive]
449
+
450
+ r[ layout.repr.primitive.intro]
377
451
The * primitive representations* are the representations with the same names as
378
452
the primitive integer types. That is: ` u8 ` , ` u16 ` , ` u32 ` , ` u64 ` , ` u128 ` ,
379
453
` usize ` , ` i8 ` , ` i16 ` , ` i32 ` , ` i64 ` , ` i128 ` , and ` isize ` .
380
454
455
+ r[ layout.repr.primitive.constraint]
381
456
Primitive representations can only be applied to enumerations and have
382
457
different behavior whether the enum has fields or no fields. It is an error
383
458
for [ zero-variant enums] to have a primitive representation. Combining
384
459
two primitive representations together is an error.
385
460
386
461
#### Primitive Representation of Field-less Enums
387
462
463
+ r[ layout.repr.primitive.enum]
464
+
388
465
For [ field-less enums] , primitive representations set the size and alignment to
389
466
be the same as the primitive type of the same name. For example, a field-less
390
467
enum with a ` u8 ` representation can only have discriminants between 0 and 255
391
468
inclusive.
392
469
393
470
#### Primitive Representation of Enums With Fields
394
471
472
+ r[ layout.repr.primitive.adt]
473
+
395
474
The representation of a primitive representation enum is a ` repr(C) ` union of
396
475
` repr(C) ` structs for each variant with a field. The first field of each struct
397
476
in the union is the primitive representation version of the enum with all fields
@@ -446,6 +525,8 @@ struct MyVariantD(MyEnumDiscriminant);
446
525
447
526
#### Combining primitive representations of enums with fields and ` #[repr(C)] `
448
527
528
+ r[ layout.repr.primitive-c]
529
+
449
530
For enums with fields, it is also possible to combine ` repr(C) ` and a
450
531
primitive representation (e.g., ` repr(C, u8) ` ). This modifies the [ ` repr(C) ` ] by
451
532
changing the representation of the discriminant enum to the chosen primitive
@@ -510,6 +591,9 @@ assert_eq!(std::mem::size_of::<Enum16>(), 4);
510
591
511
592
### The alignment modifiers
512
593
594
+ r[ layout.repr.alignment]
595
+
596
+ r[ layout.repr.alignment.intro]
513
597
The ` align ` and ` packed ` modifiers can be used to respectively raise or lower
514
598
the alignment of ` struct ` s and ` union ` s. ` packed ` may also alter the padding
515
599
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
518
602
they may be combined with representations (such as ` C ` ) which do provide such
519
603
guarantees.
520
604
605
+ r[ layout.repr.alignment.constraint-alignment]
521
606
The alignment is specified as an integer parameter in the form of
522
607
` #[repr(align(x))] ` or ` #[repr(packed(x))] ` . The alignment value must be a
523
608
power of two from 1 up to 2<sup >29</sup >. For ` packed ` , if no value is given,
524
609
as in ` #[repr(packed)] ` , then the value is 1.
525
610
611
+ r[ layout.repr.alignment.align]
526
612
For ` align ` , if the specified alignment is less than the alignment of the type
527
613
without the ` align ` modifier, then the alignment is unaffected.
528
614
615
+ r[ layout.repr.alignment.packed]
529
616
For ` packed ` , if the specified alignment is greater than the type's alignment
530
617
without the ` packed ` modifier, then the alignment and layout is unaffected.
618
+
619
+ r[ layout.repr.alignment.packed-fields]
531
620
The alignments of each field, for the purpose of positioning fields, is the
532
621
smaller of the specified alignment and the alignment of the field's type.
622
+
623
+ r[ layout.repr.alignment.packed-padding]
533
624
Inter-field padding is guaranteed to be the minimum required in order to
534
625
satisfy each field's (possibly altered) alignment (although note that, on its
535
626
own, ` packed ` does not provide any guarantee about field ordering). An
536
627
important consequence of these rules is that a type with ` #[repr(packed(1))] `
537
628
(or ` #[repr(packed)] ` ) will have no inter-field padding.
538
629
630
+ r[ layout.repr.alignment.constraint-exclusive]
539
631
The ` align ` and ` packed ` modifiers cannot be applied on the same type and a
540
632
` packed ` type cannot transitively contain another ` align ` ed type. ` align ` and
541
633
` packed ` may only be applied to the [ ` Rust ` ] and [ ` C ` ] representations.
542
634
635
+ r[ layout.repr.alignment.enum]
543
636
The ` align ` modifier can also be applied on an ` enum ` .
544
637
When it is, the effect on the ` enum ` 's alignment is the same as if the ` enum `
545
638
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.
569
662
570
663
### The `transparent ` Representation
571
664
665
+ r [layout . repr. transparent]
666
+
667
+ r [layout . repr. transparent. constraint- field ]
572
668
The `transparent ` representation can only be used on a [`struct `][structs ]
573
669
or an [`enum `][enumerations ] with a single variant that has :
574
670
- any number of fields with size 0 and alignment 1 (e . g. [`PhantomData <T >`]), and
575
671
- at most one other field .
576
672
673
+ r [layout . repr. transparent. layout- abi ]
577
674
Structs and enums with this representation have the same layout and ABI
578
675
as the only non - size 0 non - alignment 1 field , if present , or unit otherwise .
579
676
@@ -582,6 +679,7 @@ a struct with the `C` representation will always have the ABI of a `C` `struct`
582
679
while , for example , a struct with the `transparent ` representation with a
583
680
primitive field will have the ABI of the primitive field .
584
681
682
+ r [layout . repr. transparent. constraint- exclusive ]
585
683
Because this representation delegates type layout to another type , it cannot be
586
684
used with any other representation .
587
685
0 commit comments