@@ -224,27 +224,68 @@ assert_eq!(std::mem::align_of::<SizeRoundedUp>(), 4); // From a
224
224
225
225
#### \# [ repr(C)] Enums
226
226
227
- For [ C-like enumerations ] , the ` C ` representation has the size and alignment of
227
+ For [ field-less enums ] , the ` C ` representation has the size and alignment of
228
228
the default ` enum ` size and alignment for the target platform's C ABI.
229
229
230
230
> Note: The enum representation in C is implementation defined, so this is
231
231
> really a "best guess". In particular, this may be incorrect when the C code
232
232
> of interest is compiled with certain flags.
233
233
234
234
> Warning: There are crucial differences between an ` enum ` in the C language and
235
- > Rust's C-like enumerations with this representation. An ` enum ` in C is
235
+ > Rust's field-less enumerations with this representation. An ` enum ` in C is
236
236
> mostly a ` typedef ` plus some named constants; in other words, an object of an
237
237
> ` enum ` type can hold any integer value. For example, this is often used for
238
- > bitflags in ` C ` . In contrast, Rust’s C-like enumerations can only legally hold
238
+ > bitflags in ` C ` . In contrast, Rust’s field-less enums can only legally hold
239
239
> the discrimnant values, everything else is undefined behaviour. Therefore,
240
- > using a C-like enumeration in FFI to model a C ` enum ` is often wrong.
240
+ > using a field-less enum in FFI to model a C ` enum ` is often wrong.
241
241
242
- It is an error for [ zero-variant enumerations] to have the ` C ` representation.
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
245
244
- For all other enumerations, the layout is unspecified.
246
+ ``` rust
247
+ // This Enum has the same layout as
248
+ #[repr(C )]
249
+ enum MyEnum {
250
+ A (u32 ),
251
+ B (f32 , u64 ),
252
+ C { x : u32 , y : u8 },
253
+ D ,
254
+ }
245
255
246
- Likewise, combining the ` C ` representation with a primitive representation, the
247
- layout is unspecified.
256
+ // this struct.
257
+ #[repr(C )]
258
+ struct MyEnumRepr {
259
+ tag : MyEnumTag ,
260
+ payload : MyEnumPayload ,
261
+ }
262
+
263
+ #[repr(C )]
264
+ enum MyEnumTag { A , B , C , D }
265
+
266
+ #[repr(C )]
267
+ union MyEnumPayload {
268
+ A : u32 ,
269
+ B : MyEnumPayloadB ,
270
+ C : MyEnumPayloadC ,
271
+ D : (),
272
+ }
273
+
274
+ #[repr(C )]
275
+ struct MyEnumPayloadB (f32 , u64 );
276
+
277
+ #[repr(C )]
278
+ struct MyEnumPayloadC { x : u32 , y : u8 }
279
+ ```
280
+
281
+ It is an error for [ zero-variant enumerations] to have the ` C ` representation.
282
+
283
+ <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 >
248
289
249
290
### Primitive representations
250
291
@@ -254,16 +295,65 @@ the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `usize`, `i8`,
254
295
255
296
Primitive representations can only be applied to enumerations.
256
297
257
- For [ C-like enumerations] , they set the size and alignment to be the same as the
258
- primitive type of the same name. For example, a C-like enumeration with a ` u8 `
259
- representation can only have discriminants between 0 and 255 inclusive.
298
+ For [ field-less enums] , they set the size and alignment to be the same as
299
+ the primitive type of the same name. For example, a field-less enum with
300
+ a ` u8 ` representation can only have discriminants between 0 and 255 inclusive.
301
+
302
+ For enums with fields, the enum will have the same type layout a union with the
303
+ ` C ` representation that's fields consist of structs with the ` C ` representation
304
+ corresponding to each variant in the enum. The first field in each struct is
305
+ the same field-less enum with the same primitive representation that is
306
+ the enum with all fields in its variants removed and the rest of the fields
307
+ consisting of the fields of the corresponding variant in the order defined in
308
+ original enumeration.
309
+
310
+ > Note: This is commonly different than what is done in C and C++. Projects in
311
+ > those languages often use a tuple of ` (enum, payload) ` . For making your enum
312
+ > represented like that, see [ the tagged union representation] below.
313
+
314
+ ``` rust
315
+ // This custom enum
316
+ #[repr(u8 )]
317
+ enum MyEnum {
318
+ A (u32 ),
319
+ B (f32 , u64 ),
320
+ C { x : u32 , y : u8 },
321
+ D ,
322
+ }
323
+
324
+ // has the same type layout as this union
325
+ #[repr(C )]
326
+ union MyEnumRepr {
327
+ A : MyEnumVariantA ,
328
+ B : MyEnumVariantB ,
329
+ C : MyEnumVariantC ,
330
+ D : MyEnumVariantD ,
331
+ }
332
+
333
+ #[repr(u8 )]
334
+ enum MyEnumDiscriminant { A , B , C , D }
335
+
336
+ #[repr(C )]
337
+ struct MyEnumVariantA (MyEnumDiscriminant , u32 );
338
+
339
+ #[repr(C )]
340
+ struct MyEnumVariantB (MyEnumDiscriminant , f32 , u64 );
341
+
342
+ #[repr(C )]
343
+ struct MyEnumVariantC { tag : MyEnumDiscriminant , x : u32 , y : u8 }
344
+
345
+ #[repr(C )]
346
+ struct MyEnumVariantD (MyEnumDiscriminant );
347
+ ```
260
348
261
349
It is an error for [ zero-variant enumerations] to have a primitive
262
350
representation.
263
351
264
- For all other enumerations, the layout is unspecified.
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 ] .
265
356
266
- Likewise, combining two primitive representations together is unspecified.
267
357
268
358
### The ` align ` Representation
269
359
@@ -298,7 +388,8 @@ a `packed` type cannot transitively contain another `align`ed type.
298
388
[ `size_of` ] : ../std/mem/fn.size_of.html
299
389
[ `Sized` ] : ../std/marker/trait.Sized.html
300
390
[ dynamically sized types ] : dynamically-sized-types.html
301
- [ C-like enumerations ] : items/enumerations.html#custom-discriminant-values-for-field-less-enumerations
391
+ [ field-less enums ] : items/enumerations.html#custom-discriminant-values-for-field-less-enumerations
302
392
[ zero-variant enumerations ] : items/enumerations.html#zero-variant-enums
303
393
[ undefined behavior ] : behavior-considered-undefined.html
304
394
[ 27060 ] : https://github.com/rust-lang/rust/issues/27060
395
+ [ primitive representation ] : #primitive-representations
0 commit comments