How are Swift enums implemented internally?

Viewed 81

I recently asked a question around sort of generic enum/structs in C and realized that although I brought up a comparison with the enum possibilities in e.g. Swift and Rust, I don't really understand how those are handled internally to those languages.

For Rust, I found a (rather roundabout) article titled Peeking inside a Rust enum — look for the "But Rust enums aren't just that." heading and then keep scrolling until the "In Rust, it's called a discriminant." part. Eventually that part gets around to basically saying that Rust enums are sort of equivalent to something like this in C:

struct {
   enum actual_options discriminant;
   union {
      /* … various data types/sub-structs corresponding to each option's need… */
   };
};

Is it basically the same with a Swift enum under the hood? I.e. that I should expect an enum to have basically the same memory overhead as a struct of the largest possible option in my enum, plus at least one extra byte to store the tag/discriminant of the overarching case?

I'm also interested in what code gets generated to use whatever sort of underlying structure. I'm assuming it can't really much more fancy/optimized than what you'd do in C for the structure shown above? E.g.

struct raw_enum {
   enum { case1, case2, case3 } tag;
   union {
      struct { int x; int y; } case1_data;
      const char* case2_data;
      struct { float a; double b; void* c; char d; } case3_data;
   };
};


struct raw_enum d;
fill_in_some_value(&d);
if (d.tag == case1) {
  // use `d.case1_data`…
} else if (d.tag == case2) {
  // use `d.case2_data`…
} else if (d.tag == case3) {
  // use `d.case3_data`…
} else {
  // any runtime assertion for an unknown tag that could somehow sneak in???
}

Is that a reasonable approximation to what Swift does in the code it generates around enums?

0 Answers
Related