Enums: plain and tagged
Plain enums
A plain enum is a C-like set of named constants. It lowers to i32 and is Copy:
enum Color { Red, Green, Blue }
let c = Color::Red;
Tagged enums (sum types)
A tagged enum carries data with each variant. This is how C+ models "one of several shapes", and it is the foundation of error handling:
enum Shape {
Circle(f64),
Rectangle(f64, f64),
Square(f64),
}
let s = Shape::Circle(3.14);
Generic enums
Enums can be generic over a type parameter, written with [T] (not <T>):
enum Maybe[T] {
Some(T),
None,
}
let m: Maybe[i32] = Maybe[i32]::Some(7);
let n: Maybe[i32] = Maybe[i32]::None;
Always write the type arguments at the source level: Option[i32]::Some(v), Option[i32]::None. Internal mangled names like Option__i32 exist but are never something you type.
You consume an enum by pattern matching on its variants.
== / != on a payload-carrying enum is E0302 ("match on the variants instead"). The comparison previously escaped type-check and died as invalid LLVM IR. Payload-free enums still compare by discriminant.
FFI enums: explicit discriminants and #[repr]
A payload-free enum may take C-style values and an integer representation. That is what it lowers to and what it crosses the C ABI as.
#[repr(u8)]
enum Mode { Off = 0, Slow = 10, Fast = 200 }
enum Status { Ok, NotFound = 404, Gone } // Gone = 405 (prev + 1)
Discriminants are any constant expression (they fold). Unspecified values are prev + 1. #[repr(C)] is i32. Casts read the declared value; match switches on it.
Wrong shapes are E0923: a payload enum with values or an integer repr, an out-of-range value, or a duplicate value.