How does C perform rusty `Cow` enum?

I'm thinking about the basic logic of Rusty enum. As the example, Cow has two members of ref and value, with 1 usize and ?Sized usizes.

For example, size_of::<Cow<String>>() shows up 24. In Clang, how to explain such struction? How are different type sizes together in one enum type? Or, is it really single type of rusty enum declaration?

Rust enums are like C tagged unions, roughly. Each variant of an enum occupies the same space, just like in a C union.

Is that what you were asking?

1 Like

The representation of enums isn't specified by default, but you can use attributes to make it specified.

See here for a description of the specifed layouts.

1 Like

Thanks! This is useful for me

#[repr(Int)] on a non-C-like enum will now mean: the enum must be represented as a C-union of C-structs that each start with a C-like enum with #[repr(Int)]. The other fields of the structs are the payloads of the variants. This is a mouthful, so let’s look at an example. This definition:

#[repr(Int)]
enum MyEnum {
    A(u32),
    B(f32, u64),
    C { x: u32, y: u8 },
    D,
}

Has the same layout as the following:

#[repr(C)]
union MyEnumRepr {
    A: MyEnumVariantA,
    B: MyEnumVariantB,
    C: MyEnumVariantC,
    D: MyEnumVariantD,
}

#[repr(Int)]
enum MyEnumTag { A, B, C, D }

#[repr(C)]
struct MyEnumVariantA(MyEnumTag, u32);

#[repr(C)]
struct MyEnumVariantB(MyEnumTag, f32, u64);

#[repr(C)]
struct MyEnumVariantC { tag: MyEnumTag, x: u32, y: u8 }

#[repr(C)]
struct MyEnumVariantD(MyEnumTag);

Note that the structs must be repr(C), because otherwise the MyEnumTag value wouldn’t be guaranteed to have the same position in each variant.

C++ can also correctly manipulate this enum with the following definition:

#include <stdint.h>

enum class MyEnumTag: CppEquivalentOfInt { A, B, C, D };
struct MyEnumPayloadA { MyEnumTag tag; uint32_t payload; };
struct MyEnumPayloadB { MyEnumTag tag; float _0; uint64_t _1;  };
struct MyEnumPayloadC { MyEnumTag tag; uint32_t x; uint8_t y; };
struct MyEnumPayloadD { MyEnumTag tag; };

union MyEnum {
    MyEnumVariantA A;
    MyEnumVariantB B;
    MyEnumVariantC C;
    MyEnumVariantD D;
};

This is a verbatim copy-paste from RFC 2195, so it would be good to make clear it is a quotation and mention the source.

1 Like