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