lang::enum¶
Sum type declaration with payload-carrying variants.
Variants carry tuple payloads (Line(i64), Rect(i64, i64)), struct
payloads (Named { id: i64 }), or nothing (Dot). Recursive payloads
work directly with no wrapper - enum List { Cons(i64, List), Nil } -
because every variant payload is already heap-shared. The List /
List / List spellings are transparent and compile to the
same thing, so reach for them only when the type reads clearer with the
wrapper. Match exhaustively.
Variant names¶
A variant belongs to its enum, so two enums may declare variants of the same name, in one module or in different ones:
enum Conn { Ready, Closed }
enum Job { Ready, Pending }
fn describe(c: Conn) -> String {
match c {
Conn::Ready => "ready",
Conn::Closed => "closed",
}
}
fn main() {
println(describe(Conn::Ready))
let j = Job::Ready
println("{}", j == Job::Ready)
}
A bare variant name resolves to the enum the current module declares, or
to the one enum in the program that declares it. A bare name two enums in
the current module share is ambiguous and reported with the qualified
spelling (GR0009); an enum in another module never makes a bare name in
this one ambiguous.
Compare by value, no derive¶
Enums are value types, so == / != / < / <= / > / >= are
synthesized automatically - no #[derive] needed - whenever every
payload is comparable. Ordering is by variant rank first (declaration
order), then payload lexicographically:
enum Shape { Dot, Line(i64), Box(i64, i64) }
println("{}", Shape::Dot < Shape::Line(0)) // true: Dot ranks before Line
println("{}", Shape::Line(1) < Shape::Line(2)) // true: same rank, payload compared
println("{}", Shape::Box(1, 2) == Shape::Box(1, 2))
A user impl of eq / cmp overrides the synthesized one for custom
ordering.
Derivable traits¶
#[derive(...)] covers Debug, Default, PartialEq, Eq,
PartialOrd, and Ord for tuple, unit, and struct-payload variants;
#[default] marks the Default variant. The derive only forces
synthesis where the automatic gate is conservative (generic or
container-typed payloads).
Clone, Copy, Hash, Display, Serialize, and Deserialize are
not derivable (GT0025) - copying, hashing, and serialization are
automatic. The enum cap is 256 variants (GT0012).
How wide the discriminant is¶
A plain enum stores its discriminant in the smallest byte-aligned
width that holds every variant. packed asks for the smallest number of
bits instead, and a : uN names a width outright - any unsigned width
from u1 to u64:
enum Level: u16 { Debug, Warn, Error } // 16 bits, as asked
packed enum Direction { North, East, South, West } // 2 bits
packed enum Bit: u1 { Off, On } // exactly 1 bit
A width too narrow for the variants reports GT0081 with the width they
need; a representation that is not an unsigned width reports GP0050.
Variants number from zero in declaration order.
The choice is about storage only. Matching, ==, ordering, {} and
{:?}, serialization, Map keys, arrays, and tuples all behave
identically at every width, on the VM and both compiled tiers.
packed is a keyword only directly before enum, so a value or a
function may still be named packed.