@@ -21,23 +21,25 @@ An enum is said to be *C-like* if none of its variants have associated data.
21
21
For all these, individual fields are aligned to their preferred alignment. For
22
22
primitives this is usually equal to their size. For instance, a u32 will be
23
23
aligned to a multiple of 32 bits, and a u16 will be aligned to a multiple of 16
24
- bits. Composite structures will have their size rounded up to be a multiple of
25
- the highest alignment required by their fields, and an alignment requirement
26
- equal to the highest alignment required by their fields. So for instance,
24
+ bits. Composite structures will have a preferred alignment equal to the maximum
25
+ of their fields' preferred alignment, and a size equal to a multiple of their
26
+ preferred alignment. This ensures that arrays of T can be correctly iterated
27
+ by offsetting by their size. So for instance,
27
28
28
29
``` rust
29
30
struct A {
30
31
a : u8 ,
31
- c : u64 ,
32
- b : u32 ,
32
+ c : u32 ,
33
+ b : u16 ,
33
34
}
34
35
```
35
36
36
- will have a size that is a multiple of 64 -bits, and 64 -bit alignment.
37
+ will have a size that is a multiple of 32 -bits, and 32 -bit alignment.
37
38
38
39
There is * no indirection* for these types; all data is stored contiguously as you would
39
- expect in C. However with the exception of arrays, the layout of data is not by
40
- default specified in Rust. Given the two following struct definitions:
40
+ expect in C. However with the exception of arrays (which are densely packed and
41
+ in-order), the layout of data is not by default specified in Rust. Given the two
42
+ following struct definitions:
41
43
42
44
``` rust
43
45
struct A {
@@ -91,9 +93,9 @@ struct Foo<u32, u16> {
91
93
```
92
94
93
95
The latter case quite simply wastes space. An optimal use of space therefore requires
94
- different monomorphizations to * have different field orderings* .
96
+ different monomorphizations to have * different field orderings* .
95
97
96
- ** Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0.0 **
98
+ ** Note: this is a hypothetical optimization that is not yet implemented in Rust 1.0**
97
99
98
100
Enums make this consideration even more complicated. Naively, an enum such as:
99
101
@@ -120,31 +122,32 @@ such a representation is ineffiecient. The classic case of this is Rust's
120
122
"null pointer optimization". Given a pointer that is known to not be null
121
123
(e.g. ` &u32 ` ), an enum can * store* a discriminant bit * inside* the pointer
122
124
by using null as a special value. The net result is that
123
- ` sizeof( Option<&T>) == sizeof <&T>`
125
+ ` size_of::< Option<&T>>( ) == size_of:: <&T>() `
124
126
125
- There are many types in Rust that are, or contain, "not null" pointers such as ` Box<T> ` , ` Vec<T> ` ,
126
- ` String ` , ` &T ` , and ` &mut T ` . Similarly, one can imagine nested enums pooling their tags into
127
- a single descriminant, as they are by definition known to have a limited range of valid values.
128
- In principle enums can use fairly elaborate algorithms to cache bits throughout nested types
129
- with special constrained representations. As such it is * especially* desirable that we leave
130
- enum layout unspecified today.
127
+ There are many types in Rust that are, or contain, "not null" pointers such as
128
+ ` Box<T> ` , ` Vec<T> ` , ` String ` , ` &T ` , and ` &mut T ` . Similarly, one can imagine
129
+ nested enums pooling their tags into a single descriminant, as they are by
130
+ definition known to have a limited range of valid values. In principle enums can
131
+ use fairly elaborate algorithms to cache bits throughout nested types with
132
+ special constrained representations. As such it is * especially* desirable that
133
+ we leave enum layout unspecified today.
131
134
132
135
133
136
134
137
135
138
# Dynamically Sized Types (DSTs)
136
139
137
140
Rust also supports types without a statically known size. On the surface,
138
- this is a bit nonsensical: Rust must know the size of something in order to
139
- work with it. DSTs are generally produced as views, or through type-erasure
141
+ this is a bit nonsensical: Rust * must* know the size of something in order to
142
+ work with it! DSTs are generally produced as views, or through type-erasure
140
143
of types that * do* have a known size. Due to their lack of a statically known
141
144
size, these types can only exist * behind* some kind of pointer. They consequently
142
145
produce a * fat* pointer consisting of the pointer and the information that
143
146
* completes* them.
144
147
145
148
For instance, the slice type, ` [T] ` , is some statically unknown number of elements
146
149
stored contiguously. ` &[T] ` consequently consists of a ` (&T, usize) ` pair that specifies
147
- where the slice starts, and how many elements it contains. Similarly Trait Objects
150
+ where the slice starts, and how many elements it contains. Similarly, Trait Objects
148
151
support interface-oriented type erasure through a ` (data_ptr, vtable_ptr) ` pair.
149
152
150
153
Structs can actually store a single DST directly as their last field, but this
@@ -158,6 +161,8 @@ struct Foo {
158
161
}
159
162
```
160
163
164
+ ** NOTE: As of Rust 1.0 struct DSTs are broken if the last field has
165
+ a variable position based on its alignment.**
161
166
162
167
163
168
@@ -235,6 +240,7 @@ Rust allows you to specify alternative data layout strategies from the default.
235
240
236
241
237
242
243
+
238
244
## repr(C)
239
245
240
246
This is the most important ` repr ` . It has fairly simple intent: do what C does.
@@ -262,6 +268,7 @@ the FFI boundary.
262
268
263
269
264
270
271
+
265
272
## repr(packed)
266
273
267
274
` repr(packed) ` forces rust to strip any padding, and only align the type to a
@@ -278,11 +285,13 @@ this should not be used.
278
285
This repr is a modifier on ` repr(C) ` and ` repr(rust) ` .
279
286
280
287
288
+
289
+
281
290
## repr(u8), repr(u16), repr(u32), repr(u64)
282
291
283
292
These specify the size to make a C-like enum. If the discriminant overflows the
284
293
integer it has to fit in, it will be an error. You can manually ask Rust to
285
294
allow this by setting the overflowing element to explicitly be 0. However Rust
286
295
will not allow you to create an enum where two variants.
287
296
288
- These reprs have no affect on struct or non-C-like enum.
297
+ These reprs have no affect on a struct or non-C-like enum.
0 commit comments