@@ -149,7 +149,8 @@ layout such as reinterpreting values as a different type.
149
149
Because of this dual purpose, it is possible to create types that are not useful
150
150
for interfacing with the C programming language.
151
151
152
- This representation can be applied to structs, unions, and enums.
152
+ This representation can be applied to structs, unions, and enums. The exception
153
+ is [ zero-variant enumerations] for which the ` C ` representation is an error.
153
154
154
155
#### \# [ repr(C)] Structs
155
156
@@ -222,7 +223,7 @@ assert_eq!(std::mem::size_of::<SizeRoundedUp>(), 8); // Size of 6 from b,
222
223
assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
223
224
```
224
225
225
- #### \# [ repr(C)] Enums
226
+ #### \# [ repr(C)] Field-less Enums
226
227
227
228
For [ field-less enums] , the ` C ` representation has the size and alignment of
228
229
the default ` enum ` size and alignment for the target platform's C ABI.
@@ -236,12 +237,21 @@ the default `enum` size and alignment for the target platform's C ABI.
236
237
> mostly a ` typedef ` plus some named constants; in other words, an object of an
237
238
> ` enum ` type can hold any integer value. For example, this is often used for
238
239
> bitflags in ` C ` . In contrast, Rust’s field-less enums can only legally hold
239
- > the discrimnant values, everything else is undefined behaviour . Therefore,
240
+ > the discrimnant values, everything else is [ undefined behavior ] . Therefore,
240
241
> using a field-less enum in FFI to model a C ` enum ` is often wrong.
241
242
242
- For enums with fields, the ` C ` representation has the same representation as
243
- it would with the [ primitive representation] with the field-less enum in its
244
- description having the ` C ` representation.
243
+ #### \# [ repr(C)] Enums With Fields
244
+
245
+ For enums with fields, the ` C ` representation is a struct with representation
246
+ ` C ` of two fields where the first field is a field-less enum with the ` C `
247
+ representation that has one variant for each variant in the enum with fields
248
+ and the second field a union with the ` C ` representation that's fields consist
249
+ of structs with the ` C ` representation corresponding to each variant in the
250
+ enum. Each struct consists of the fields from the corresponding variant in the
251
+ order defined in the enum with fields.
252
+
253
+ Because unions with non-copy fields aren't allowed, this representation can only
254
+ be used if every field is also [ ` Copy ` ] .
245
255
246
256
``` rust
247
257
// This Enum has the same layout as
@@ -272,33 +282,51 @@ union MyEnumPayload {
272
282
}
273
283
274
284
#[repr(C )]
285
+ #[derive(Clone , Copy )]
275
286
struct MyEnumPayloadB (f32 , u64 );
276
287
277
288
#[repr(C )]
289
+ #[derive(Clone , Copy )]
278
290
struct MyEnumPayloadC { x : u32 , y : u8 }
279
291
```
280
292
281
- It is an error for [ zero-variant enumerations] to have the ` C ` representation.
282
-
283
293
<span id =" c-primitive-representation " >Combining the ` C ` representation and a
284
- primitive representation is only defined for enums with fields and it changes
285
- the representation of the tag, e.g. ` MyEnumTag ` in the previous example, to have
286
- the representation of the chosen primitive representation. So, if you chose the
287
- ` u8 ` representation, then the tag would have a size and alignment of 1 byte.
288
- </span >
294
+ primitive representation is only defined for enums with fields. The primitive
295
+ representation modifies the ` C ` representation by changing the representation of
296
+ the tag, e.g. ` MyEnumTag ` in the previous example, to have the representation of
297
+ the chosen primitive representation. So, if you chose the ` u8 ` representation,
298
+ then the tag would have a size and alignment of 1 byte. </span >
289
299
290
- ### Primitive representations
300
+ > Note: This representation was designed for primarily interfacing with C code
301
+ > that already exists matching a common way Rust's enums are implemented in
302
+ > C. If you have control over both the Rust and C code, such as using C as FFI
303
+ > glue between Rust and some third language, then you should use a
304
+ > [ primitive representation] ( #primitive-representation-of-enums-with-fields )
305
+ > instead.
306
+
307
+ ### Primitive Representations
291
308
292
309
The * primitive representations* are the representations with the same names as
293
310
the primitive integer types. That is: ` u8 ` , ` u16 ` , ` u32 ` , ` u64 ` , ` usize ` , ` i8 ` ,
294
311
` i16 ` , ` i32 ` , ` i64 ` , and ` isize ` .
295
312
296
- Primitive representations can only be applied to enumerations.
313
+ Primitive representations can only be applied to enumerations, and have
314
+ different behavior whether the enum has fields or no fields. It is an error
315
+ for [ zero-variant enumerations] to have a primitive representation.
316
+
317
+ Combining two primitive representations together is unspecified.
318
+
319
+ Combining the ` C ` representation and a primitive representation is described
320
+ [ above] ( #c-primitive-representation ) .
321
+
322
+ #### Primitive Fepresentation of Field-less Enums
297
323
298
324
For [ field-less enums] , they set the size and alignment to be the same as
299
325
the primitive type of the same name. For example, a field-less enum with
300
326
a ` u8 ` representation can only have discriminants between 0 and 255 inclusive.
301
327
328
+ #### Primitive Representation of Enums With Fields
329
+
302
330
For enums with fields, the enum will have the same type layout a union with the
303
331
` C ` representation that's fields consist of structs with the ` C ` representation
304
332
corresponding to each variant in the enum. The first field in each struct is
@@ -307,9 +335,12 @@ the enum with all fields in its variants removed and the rest of the fields
307
335
consisting of the fields of the corresponding variant in the order defined in
308
336
original enumeration.
309
337
338
+ Because unions with non-copy fields aren't allowed, this representation can only
339
+ be used if every field is also [ ` Copy ` ] .
340
+
310
341
> Note: This is commonly different than what is done in C and C++. Projects in
311
342
> those languages often use a tuple of ` (enum, payload) ` . For making your enum
312
- > represented like that, see [ the tagged union representation] below .
343
+ > represented like that, use the ` C ` representation.
313
344
314
345
``` rust
315
346
// This custom enum
@@ -323,6 +354,7 @@ enum MyEnum {
323
354
324
355
// has the same type layout as this union
325
356
#[repr(C )]
357
+ #[derive(Clone , Copy )]
326
358
union MyEnumRepr {
327
359
A : MyEnumVariantA ,
328
360
B : MyEnumVariantB ,
@@ -331,30 +363,26 @@ union MyEnumRepr {
331
363
}
332
364
333
365
#[repr(u8 )]
366
+ #[derive(Clone , Copy )]
334
367
enum MyEnumDiscriminant { A , B , C , D }
335
368
336
369
#[repr(C )]
370
+ #[derive(Clone , Copy )]
337
371
struct MyEnumVariantA (MyEnumDiscriminant , u32 );
338
372
339
373
#[repr(C )]
374
+ #[derive(Clone , Copy )]
340
375
struct MyEnumVariantB (MyEnumDiscriminant , f32 , u64 );
341
376
342
377
#[repr(C )]
378
+ #[derive(Clone , Copy )]
343
379
struct MyEnumVariantC { tag : MyEnumDiscriminant , x : u32 , y : u8 }
344
380
345
381
#[repr(C )]
382
+ #[derive(Clone , Copy )]
346
383
struct MyEnumVariantD (MyEnumDiscriminant );
347
384
```
348
385
349
- It is an error for [ zero-variant enumerations] to have a primitive
350
- representation.
351
-
352
- Combining two primitive representations together is unspecified.
353
-
354
- Combining the ` C ` representation and a primitive representation is described
355
- [ above] [ #c-primitive-representation ] .
356
-
357
-
358
386
### The ` align ` Representation
359
387
360
388
The ` align ` representation can be used on ` struct ` s and ` union ` s to raise the
@@ -378,7 +406,7 @@ padding bytes and forcing the alignment of the type to `1`.
378
406
The ` align ` and ` packed ` representations cannot be applied on the same type and
379
407
a ` packed ` type cannot transitively contain another ` align ` ed type.
380
408
381
- > Warning: Dereferencing an unaligned pointer is [ undefined behaviour ] and it is
409
+ > Warning: Dereferencing an unaligned pointer is [ undefined behavior ] and it is
382
410
> possible to [ safely create unaligned pointers to ` packed ` fields] [ 27060 ] .
383
411
> Like all ways to create undefined behavior in safe Rust, this is a bug.
384
412
@@ -392,4 +420,5 @@ a `packed` type cannot transitively contain another `align`ed type.
392
420
[ zero-variant enumerations ] : items/enumerations.html#zero-variant-enums
393
421
[ undefined behavior ] : behavior-considered-undefined.html
394
422
[ 27060 ] : https://github.com/rust-lang/rust/issues/27060
395
- [ primitive representation ] : #primitive-representations
423
+ [ primitive representation ] : #primitive-representations
424
+ [ `Copy` ] : special-types-and-traits.html#copy
0 commit comments