One caveat to this is the "Enum with inner structs" version only avoids overhead when using individual shapes. The inner struct doesn't affect the enum size and alignment, so you still will have 12 bytes per shape in collections (8 for the largest shape variant's fields, 1 for the discriminant, and 3 for padding).