@@ -351,90 +351,73 @@ enum Enum1<T> {
351
351
}
352
352
```
353
353
354
- ## Unresolved questions
355
-
356
354
### Layout of single variant enums
357
355
358
- [Issue #79 .](https:// github.com/rust-rfcs/unsafe-code-guidelines/issues/79)
359
-
360
- Enums that contain a **single variant** and which do not have an
361
- explicit `#[repr]` annotation are an important special case . Since
362
- there is only a single variant, the enum must be instantiated with
363
- that variant, which means that the enum is in fact equivalent to a
364
- struct . The question then is to what extent we should ** guarantee**
365
- that the two share an equivalent layout, and also how to define the
366
- interaction with uninhabited types.
356
+ ** Single variant data-carrying*** enums without a ` repr() ` annotation have the
357
+ same layout as the variant field. ** Single variant fieldless** enums have the
358
+ same layout as a unit struct.
367
359
368
- As presently implemented, the compiler will use the same layout for
369
- structs and for single variant enums (as long as they do not have a
370
- ` #[repr] ` annotation that overrides that choice). So, for example, the
371
- struct ` SomeStruct ` and the enum ` SomeEnum ` would have an equivalent
372
- layout ([ playground] ( https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3697ac684c3d021892694956df957653 ) ):
360
+ Here:
373
361
374
362
``` rust
375
- struct SomeStruct ;
376
- enum SomeEnum {
377
- SomeVariant ,
378
- }
379
-
363
+ # use std :: mem :: {size_of, align_of};
364
+ struct UnitStruct ;
365
+ enum SingleVariantFieldless { FieldlessVariant }
380
366
# fn main () {
381
- # use std :: mem;
382
- let x = SomeStruct ;
383
- let y = SomeEnum :: SomeVariant ;
384
- assert_eq! (
385
- mem :: size_of_val (& x ),
386
- mem :: size_of_val (& y ),
387
- " types have different sizes" ,
388
- );
389
- println! (" types both have size {}" , std :: mem :: size_of_val (& x ));
367
+ assert_eq! (size_of :: <SingleVariantFieldless >(), size_of :: <UnitStruct >());
368
+ assert_eq! (align_of :: <SingleVariantFieldless >(), align_of :: <UnitStruct >());
369
+ // assert_eq!(call_abi_of::<SingleVariantFieldless>(), call_abi_of::<UnitStruct>());
370
+ // assert_eq!(niches_of::<SingleVariantFieldless>(), niches_of::<UnitStruct>());
390
371
# }
391
372
```
392
373
393
- Similarly, the struct ` SomeStruct ` and the enum ` SomeVariant ` in this
394
- example would also be equivalent in their layout
395
- ([playground](https:// play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=924724764419f846c788a8763da45992)):
374
+ the single-variant fieldless enum ` SingleVariantFieldless ` has the same layout
375
+ as ` UnitStruct ` .
376
+
377
+ Here:
396
378
397
379
``` rust
380
+ # use std :: mem :: {size_of, align_of};
398
381
struct SomeStruct { x : u32 }
399
- enum SomeEnum {
400
- SomeVariant { x: u32 } ,
382
+ enum SingleVariantDataCarrying {
383
+ DataCarryingVariant ( SomeStruct ) ,
401
384
}
402
-
403
385
# fn main () {
404
- # use std::mem;
405
- let x = SomeStruct { x: 22 };
406
- let y = SomeEnum::SomeVariant { x: 22 };
407
- assert_eq!(
408
- mem::size_of_val(&x),
409
- mem::size_of_val(&y),
410
- "types have different sizes",
411
- );
412
- println!(" types both have size {}" , mem::size_of_val(&x));
413
- }
386
+ assert_eq! (size_of :: <SingleVariantDataCarrying >(), size_of :: <SomeStruct >());
387
+ assert_eq! (align_of :: <SingleVariantDataCarrying >(), align_of :: <SomeStruct >());
388
+ // assert_eq!(call_abi_of::<SingleVariantDataCarrying>(), call_abi_of::<SomeStruct>());
389
+ // assert_eq!(niches_of::<SingleVariantDataCarrying>(), niches_of::<SomeStruct>());
390
+ # }
414
391
```
415
392
416
- In fact, the compiler will use this optimized layout even for enums
417
- that define multiple variants, as long as all but one of the variants
418
- is uninhabited
419
- ([ playground] ( https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3cc1484c5b91097f3dc2015b7c207a0e ) ):
393
+ the single-variant data-carrying enum ` SingleVariantDataCarrying ` has the same
394
+ layout as ` SomeStruct ` .
395
+
396
+ ### Layout of multi-variant enums with one inhabited variant
397
+
398
+ The layout of ** multi-variant** enums with ** one inhabited variant** is the same
399
+ as that of the single-variant enum containing that same inhabited variant.
400
+
401
+ Here:
420
402
421
403
``` rust
422
- # enum Void { }
423
- struct SomeStruct { x : u32 }
424
- enum SomeEnum {
425
- SomeVariant { x : u32 },
426
- UninhabitedVariant { y : Void },
404
+ # use std :: mem :: {size_of, align_of};
405
+ # struct SomeStruct { x : u32 }
406
+ # enum SingleVariantDataCarrying {
407
+ # DataCarryingVariant (SomeStruct ),
408
+ # }
409
+ enum Void0 {}
410
+ enum Void1 {}
411
+ enum MultiVariantSingleHabited {
412
+ DataCarryingVariant (SomeStruct ),
413
+ Uninhabited0 (Void0 ),
414
+ Uninhabited1 (Void1 ),
427
415
}
428
-
429
416
# fn main () {
430
417
# use std :: mem;
431
- let x = SomeStruct { x : 22 };
432
- let y = SomeEnum :: SomeVariant { x : 22 };
433
- assert_eq! (
434
- mem :: size_of_val (& x ),
435
- mem :: size_of_val (& y ),
436
- " types have different sizes" ,
437
- );
438
- println! (" types both have size {}" , mem :: size_of_val (& x ));
418
+ assert_eq! (size_of :: <SingleVariantDataCarrying >(), size_of :: <MultiVariantSingleHabited >());
419
+ assert_eq! (align_of :: <SingleVariantDataCarrying >(), align_of :: <MultiVariantSingleHabited >());
420
+ // assert_eq!(call_abi_of::<SingleVariantDataCarrying>(), call_abi_of::<MultiVariantSingleHabited>());
421
+ // assert_eq!(niches_of::<SingleVariantDataCarrying>(), niches_of::<MultiVariantSingleHabited>());
439
422
# }
440
423
```
0 commit comments