@@ -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,46 @@ 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 >
299
+
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.
289
306
290
- ### Primitive representations
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
+ #### Primitive Fepresentation of Field-less Enums
297
318
298
319
For [ field-less enums] , they set the size and alignment to be the same as
299
320
the primitive type of the same name. For example, a field-less enum with
300
321
a ` u8 ` representation can only have discriminants between 0 and 255 inclusive.
301
322
323
+ #### Primitive Representation of Enums With Fields
324
+
302
325
For enums with fields, the enum will have the same type layout a union with the
303
326
` C ` representation that's fields consist of structs with the ` C ` representation
304
327
corresponding to each variant in the enum. The first field in each struct is
@@ -307,9 +330,12 @@ the enum with all fields in its variants removed and the rest of the fields
307
330
consisting of the fields of the corresponding variant in the order defined in
308
331
original enumeration.
309
332
333
+ Because unions with non-copy fields aren't allowed, this representation can only
334
+ be used if every field is also [ ` Copy ` ] .
335
+
310
336
> Note: This is commonly different than what is done in C and C++. Projects in
311
337
> those languages often use a tuple of ` (enum, payload) ` . For making your enum
312
- > represented like that, see [ the tagged union representation] below .
338
+ > represented like that, use the ` C ` representation.
313
339
314
340
``` rust
315
341
// This custom enum
@@ -323,6 +349,7 @@ enum MyEnum {
323
349
324
350
// has the same type layout as this union
325
351
#[repr(C )]
352
+ #[derive(Clone , Copy )]
326
353
union MyEnumRepr {
327
354
A : MyEnumVariantA ,
328
355
B : MyEnumVariantB ,
@@ -331,28 +358,30 @@ union MyEnumRepr {
331
358
}
332
359
333
360
#[repr(u8 )]
361
+ #[derive(Clone , Copy )]
334
362
enum MyEnumDiscriminant { A , B , C , D }
335
363
336
364
#[repr(C )]
365
+ #[derive(Clone , Copy )]
337
366
struct MyEnumVariantA (MyEnumDiscriminant , u32 );
338
367
339
368
#[repr(C )]
369
+ #[derive(Clone , Copy )]
340
370
struct MyEnumVariantB (MyEnumDiscriminant , f32 , u64 );
341
371
342
372
#[repr(C )]
373
+ #[derive(Clone , Copy )]
343
374
struct MyEnumVariantC { tag : MyEnumDiscriminant , x : u32 , y : u8 }
344
375
345
376
#[repr(C )]
377
+ #[derive(Clone , Copy )]
346
378
struct MyEnumVariantD (MyEnumDiscriminant );
347
379
```
348
380
349
- It is an error for [ zero-variant enumerations] to have a primitive
350
- representation.
351
-
352
381
Combining two primitive representations together is unspecified.
353
382
354
383
Combining the ` C ` representation and a primitive representation is described
355
- [ above] [ #c-primitive-representation ] .
384
+ [ above] ( #c-primitive-representation ) .
356
385
357
386
358
387
### The ` align ` Representation
@@ -378,7 +407,7 @@ padding bytes and forcing the alignment of the type to `1`.
378
407
The ` align ` and ` packed ` representations cannot be applied on the same type and
379
408
a ` packed ` type cannot transitively contain another ` align ` ed type.
380
409
381
- > Warning: Dereferencing an unaligned pointer is [ undefined behaviour ] and it is
410
+ > Warning: Dereferencing an unaligned pointer is [ undefined behavior ] and it is
382
411
> possible to [ safely create unaligned pointers to ` packed ` fields] [ 27060 ] .
383
412
> Like all ways to create undefined behavior in safe Rust, this is a bug.
384
413
@@ -392,4 +421,5 @@ a `packed` type cannot transitively contain another `align`ed type.
392
421
[ zero-variant enumerations ] : items/enumerations.html#zero-variant-enums
393
422
[ undefined behavior ] : behavior-considered-undefined.html
394
423
[ 27060 ] : https://github.com/rust-lang/rust/issues/27060
395
- [ primitive representation ] : #primitive-representations
424
+ [ primitive representation ] : #primitive-representations
425
+ [ `Copy` ] : special-types-and-traits.html#copy
0 commit comments