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
@@ -13,22 +17,26 @@ see [here][fn-abi-compatibility].
1317
1418## Size and Alignment
1519
20+ r[ layout.properties]
1621All values have an alignment and size.
1722
23+ r[ layout.properties.align]
1824The * alignment* of a value specifies what addresses are valid to store the value
1925at. A value of alignment ` n ` must only be stored at an address that is a
2026multiple of n. For example, a value with an alignment of 2 must be stored at an
2127even address, while a value with an alignment of 1 can be stored at any address.
2228Alignment is measured in bytes, and must be at least 1, and always a power of 2.
2329The alignment of a value can be checked with the [ ` align_of_val ` ] function.
2430
31+ r[ layout.properties.size]
2532The * size* of a value is the offset in bytes between successive elements in an
2633array with that item type including alignment padding. The size of a value is
2734always a multiple of its alignment. Note that some types are zero-sized; 0 is
2835considered 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
3037the [ ` size_of_val ` ] function.
3138
39+ r[ layout.properties.sized]
3240Types where all values have the same size and alignment, and both are known at
3341compile 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]
4152The 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
5769target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64
5870bit target, this is 8 bytes.
5971
72+ r[ layout.primitive.align]
6073The alignment of primitives is platform-specific.
6174In most cases, their alignment is equal to their size, but it may be less.
6275In 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]
6884Pointers and references have the same layout. Mutability of the pointer or
6985reference does not change the layout.
7086
87+ r[ layout.pointer.thin]
7188Pointers to sized types have the same size and alignment as ` usize ` .
7289
90+ r[ layout.pointer.unsized]
7391Pointers to unsized types are sized. The size and alignment is guaranteed to be
7492at 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+
82102An array of ` [T; N] ` has a size of ` size_of::<T>() * N ` and the same alignment
83103of ` T ` . Arrays are laid out so that the zero-based ` nth ` element of the array
84104is offset from the start of the array by ` n * size_of::<T>() ` bytes.
85105
86106## Slice Layout
87107
108+ r[ layout.slice]
109+
88110Slices 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+
94119String 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]
98126Tuples are laid out according to the [ ` Rust ` representation] [ `Rust` ] .
99127
128+ r[ layout.tuple.unit]
100129The exception to this is the unit tuple (` () ` ), which is guaranteed as a
101130zero-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+
105136Trait 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+
112145Closures have no layout guarantees.
113146
114147## Representations
115148
149+ r[ layout.repr]
150+
151+ r[ layout.repr.intro]
116152All 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]
125164The representation of a type can be changed by applying the ` repr ` attribute
126165to 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]
137177The alignment may be raised or lowered with the ` align ` and ` packed ` modifiers
138178respectively. They alter the representation specified in the attribute.
139179If 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]
164205The representation of a type can change the padding between fields, but does
165206not change the layout of the fields themselves. For example, a struct with a
166207` C ` representation that contains a struct ` Inner ` with the default
167208representation 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]
171215The ` Rust ` representation is the default representation for nominal types
172216without a ` repr ` attribute. Using this representation explicitly through a
173217` repr ` attribute is guaranteed to be the same as omitting the attribute
174218entirely.
175219
220+ r[ layout.repr.rust.layout]
176221The only data layout guarantees made by this representation are those required
177222for 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]
183229Formally, 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
185234ordered such that the offset plus the size of any field is less than or equal to
186235the offset of the next field in the ordering. The ordering does not have to be
187236the 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
191240addresses: zero-sized types may have the same address as other fields in the
192241same struct.
193242
243+ r[ layout.repr.rust.unspecified]
194244There 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]
198251The ` C ` representation is designed for dual purposes. One purpose is for
199252creating types that are interoperable with the C Language. The second purpose is
200253to 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.
203256Because of this dual purpose, it is possible to create types that are not useful
204257for interfacing with the C programming language.
205258
259+ r[ layout.repr.c.constraint]
206260This representation can be applied to structs, unions, and enums. The exception
207261is [ 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]
211268The alignment of the struct is the alignment of the most-aligned field in it.
212269
270+ r[ layout.repr.c.struct.size-field-offset]
213271The size and offset of fields is determined by the following algorithm.
214272
215273Start 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]
273334A union declared with ` #[repr(C)] ` will have the same size and alignment as an
274335equivalent C union declaration in the C language for the target platform.
336+
337+ r[ layout.repr.c.union.size-align]
275338The union will have a size of the maximum size of all of its fields rounded to
276339its alignment, and an alignment of the maximum alignment of all of its fields.
277340These 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+
303368For [ field-less enums] , the ` C ` representation has the size and alignment of
304369the 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]
315383The representation of a ` repr(C) ` enum with fields is a ` repr(C) ` struct with
316384two 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]
381455The * primitive representations* are the representations with the same names as
382456the 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]
385460Primitive representations can only be applied to enumerations and have
386461different behavior whether the enum has fields or no fields. It is an error
387462for [ zero-variant enums] to have a primitive representation. Combining
388463two primitive representations together is an error.
389464
390465#### Primitive Representation of Field-less Enums
391466
467+ r[ layout.repr.primitive.enum]
468+
392469For [ field-less enums] , primitive representations set the size and alignment to
393470be the same as the primitive type of the same name. For example, a field-less
394471enum with a ` u8 ` representation can only have discriminants between 0 and 255
395472inclusive.
396473
397474#### Primitive Representation of Enums With Fields
398475
476+ r[ layout.repr.primitive.adt]
477+
399478The 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
401480in 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+
453534For enums with fields, it is also possible to combine ` repr(C) ` and a
454535primitive representation (e.g., ` repr(C, u8) ` ). This modifies the [ ` repr(C) ` ] by
455536changing 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]
517601The ` align ` and ` packed ` modifiers can be used to respectively raise or lower
518602the alignment of ` struct ` s and ` union ` s. ` packed ` may also alter the padding
519603between 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
522606they may be combined with representations (such as ` C ` ) which do provide such
523607guarantees.
524608
609+ r[ layout.repr.alignment.constraint-alignment]
525610The 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
527612power of two from 1 up to 2<sup >29</sup >. For ` packed ` , if no value is given,
528613as in ` #[repr(packed)] ` , then the value is 1.
529614
615+ r[ layout.repr.alignment.align]
530616For ` align ` , if the specified alignment is less than the alignment of the type
531617without the ` align ` modifier, then the alignment is unaffected.
532618
619+ r[ layout.repr.alignment.packed]
533620For ` packed ` , if the specified alignment is greater than the type's alignment
534621without the ` packed ` modifier, then the alignment and layout is unaffected.
622+
623+ r[ layout.repr.alignment.packed-fields]
535624The alignments of each field, for the purpose of positioning fields, is the
536625smaller of the specified alignment and the alignment of the field's type.
626+
627+ r[ layout.repr.alignment.packed-padding]
537628Inter-field padding is guaranteed to be the minimum required in order to
538629satisfy each field's (possibly altered) alignment (although note that, on its
539630own, ` packed ` does not provide any guarantee about field ordering). An
540631important 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]
543635The ` 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]
547640The ` align ` modifier can also be applied on an ` enum ` .
548641When it is, the effect on the ` enum ` 's alignment is the same as if the ` enum `
549642was 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 ]
576672The `transparent ` representation can only be used on a [`struct `][structs ]
577673or 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 ]
581678Structs and enums with this representation have the same layout and ABI
582679as 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`
586683while , for example , a struct with the `transparent ` representation with a
587684primitive field will have the ABI of the primitive field .
588685
686+ r [layout . repr. transparent. constraint- exclusive ]
589687Because this representation delegates type layout to another type , it cannot be
590688used with any other representation .
591689
0 commit comments