11# Type Layout
22
3+ r[ layout]
4+
5+ r[ layout.intro]
36The layout of a type is its size, alignment, and the relative offsets of its
47fields. For enums, how the discriminant is laid out and interpreted is also part
58of type layout.
69
10+ r[ layout.guarantees]
711Type layout can be changed with each compilation. Instead of trying to document
812exactly what is done, we only document what is guaranteed today.
913
1014## Size and Alignment
1115
16+ r[ layout.properties]
1217All values have an alignment and size.
1318
19+ r[ layout.properties.align]
1420The * alignment* of a value specifies what addresses are valid to store the value
1521at. A value of alignment ` n ` must only be stored at an address that is a
1622multiple of n. For example, a value with an alignment of 2 must be stored at an
1723even address, while a value with an alignment of 1 can be stored at any address.
1824Alignment is measured in bytes, and must be at least 1, and always a power of 2.
1925The alignment of a value can be checked with the [ ` align_of_val ` ] function.
2026
27+ r[ layout.properties.size]
2128The * size* of a value is the offset in bytes between successive elements in an
2229array with that item type including alignment padding. The size of a value is
2330always a multiple of its alignment. Note that some types are zero-sized; 0 is
2431considered 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
2633the [ ` size_of_val ` ] function.
2734
35+ r[ layout.properties.sized]
2836Types where all values have the same size and alignment, and both are known at
2937compile 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]
3748The 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
5365target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
5466bit target, this is 8 bytes.
5567
68+ r[ layout.primitive.align]
5669The alignment of primitives is platform-specific.
5770In most cases, their alignment is equal to their size, but it may be less.
5871In 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]
6480Pointers and references have the same layout. Mutability of the pointer or
6581reference does not change the layout.
6682
83+ r[ layout.pointer.thin]
6784Pointers to sized types have the same size and alignment as ` usize ` .
6885
86+ r[ layout.pointer.unsized]
6987Pointers to unsized types are sized. The size and alignment is guaranteed to be
7088at 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+
7898An array of ` [T; N] ` has a size of ` size_of::<T>() * N ` and the same alignment
7999of ` T ` . Arrays are laid out so that the zero-based ` nth ` element of the array
80100is offset from the start of the array by ` n * size_of::<T>() ` bytes.
81101
82102## Slice Layout
83103
104+ r[ layout.slice]
105+
84106Slices 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+
90115String 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]
94122Tuples are laid out according to the [ ` Rust ` representation] [ `Rust` ] .
95123
124+ r[ layout.tuple.unit]
96125The exception to this is the unit tuple (` () ` ), which is guaranteed as a
97126zero-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+
101132Trait 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+
108141Closures have no layout guarantees.
109142
110143## Representations
111144
145+ r[ layout.repr]
146+
147+ r[ layout.repr.intro]
112148All 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]
121160The representation of a type can be changed by applying the ` repr ` attribute
122161to 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]
133173The alignment may be raised or lowered with the ` align ` and ` packed ` modifiers
134174respectively. They alter the representation specified in the attribute.
135175If 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]
160201The representation of a type can change the padding between fields, but does
161202not change the layout of the fields themselves. For example, a struct with a
162203` C ` representation that contains a struct ` Inner ` with the default
163204representation 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]
167211The ` Rust ` representation is the default representation for nominal types
168212without a ` repr ` attribute. Using this representation explicitly through a
169213` repr ` attribute is guaranteed to be the same as omitting the attribute
170214entirely.
171215
216+ r[ layout.repr.rust.layout]
172217The only data layout guarantees made by this representation are those required
173218for 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]
179225Formally, 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
181230ordered such that the offset plus the size of any field is less than or equal to
182231the offset of the next field in the ordering. The ordering does not have to be
183232the 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
187236addresses: zero-sized types may have the same address as other fields in the
188237same struct.
189238
239+ r[ layout.repr.rust.unspecified]
190240There 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]
194247The ` C ` representation is designed for dual purposes. One purpose is for
195248creating types that are interoperable with the C Language. The second purpose is
196249to 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.
199252Because of this dual purpose, it is possible to create types that are not useful
200253for interfacing with the C programming language.
201254
255+ r[ layout.repr.c.constraint]
202256This representation can be applied to structs, unions, and enums. The exception
203257is [ 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]
207264The alignment of the struct is the alignment of the most-aligned field in it.
208265
266+ r[ layout.repr.c.struct.size-field-offset]
209267The size and offset of fields is determined by the following algorithm.
210268
211269Start 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]
269330A union declared with ` #[repr(C)] ` will have the same size and alignment as an
270331equivalent C union declaration in the C language for the target platform.
332+
333+ r[ layout.repr.c.union.size-align]
271334The union will have a size of the maximum size of all of its fields rounded to
272335its alignment, and an alignment of the maximum alignment of all of its fields.
273336These 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+
299364For [ field-less enums] , the ` C ` representation has the size and alignment of
300365the 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]
311379The representation of a ` repr(C) ` enum with fields is a ` repr(C) ` struct with
312380two 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]
377451The * primitive representations* are the representations with the same names as
378452the 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]
381456Primitive representations can only be applied to enumerations and have
382457different behavior whether the enum has fields or no fields. It is an error
383458for [ zero-variant enums] to have a primitive representation. Combining
384459two primitive representations together is an error.
385460
386461#### Primitive Representation of Field-less Enums
387462
463+ r[ layout.repr.primitive.enum]
464+
388465For [ field-less enums] , primitive representations set the size and alignment to
389466be the same as the primitive type of the same name. For example, a field-less
390467enum with a ` u8 ` representation can only have discriminants between 0 and 255
391468inclusive.
392469
393470#### Primitive Representation of Enums With Fields
394471
472+ r[ layout.repr.primitive.adt]
473+
395474The 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
397476in 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+
449530For enums with fields, it is also possible to combine ` repr(C) ` and a
450531primitive representation (e.g., ` repr(C, u8) ` ). This modifies the [ ` repr(C) ` ] by
451532changing 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]
513597The ` align ` and ` packed ` modifiers can be used to respectively raise or lower
514598the alignment of ` struct ` s and ` union ` s. ` packed ` may also alter the padding
515599between 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
518602they may be combined with representations (such as ` C ` ) which do provide such
519603guarantees.
520604
605+ r[ layout.repr.alignment.constraint-alignment]
521606The 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
523608power of two from 1 up to 2<sup >29</sup >. For ` packed ` , if no value is given,
524609as in ` #[repr(packed)] ` , then the value is 1.
525610
611+ r[ layout.repr.alignment.align]
526612For ` align ` , if the specified alignment is less than the alignment of the type
527613without the ` align ` modifier, then the alignment is unaffected.
528614
615+ r[ layout.repr.alignment.packed]
529616For ` packed ` , if the specified alignment is greater than the type's alignment
530617without the ` packed ` modifier, then the alignment and layout is unaffected.
618+
619+ r[ layout.repr.alignment.packed-fields]
531620The alignments of each field, for the purpose of positioning fields, is the
532621smaller of the specified alignment and the alignment of the field's type.
622+
623+ r[ layout.repr.alignment.packed-padding]
533624Inter-field padding is guaranteed to be the minimum required in order to
534625satisfy each field's (possibly altered) alignment (although note that, on its
535626own, ` packed ` does not provide any guarantee about field ordering). An
536627important 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]
539631The ` 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]
543636The ` align ` modifier can also be applied on an ` enum ` .
544637When it is, the effect on the ` enum ` 's alignment is the same as if the ` enum `
545638was 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 ]
572668The `transparent ` representation can only be used on a [`struct `][structs ]
573669or 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 ]
577674Structs and enums with this representation have the same layout and ABI
578675as 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`
582679while , for example , a struct with the `transparent ` representation with a
583680primitive field will have the ABI of the primitive field .
584681
682+ r [layout . repr. transparent. constraint- exclusive ]
585683Because this representation delegates type layout to another type , it cannot be
586684used with any other representation .
587685
0 commit comments