Types, traits, and patterns
type declares a record and enum declares a closed choice of variants.
Both can have generic parameters. There is no struct keyword. Fields and
variants end with semicolons; commas separate literal values and pattern
elements.
type Pair<A, B> {
first: A;
second: B;
}
trait Label {
fn label(self) -> string;
}
type Point {
x: i64;
y: i64;
}
impl Label for Point {
fn label(self) -> string { f"({self.x}, {self.y})" }
}
enum Shape {
Dot(Point);
Rectangle { width: i64; height: i64; }
}
fn main() {
let pair = Pair { first: 3, second: "east" };
let shape = Shape.Dot(Point { x: pair.first, y: 4 });
match shape {
.Dot(point) => println(point.label()),
.Rectangle { width, height } => println(width * height),
}
}
Record construction is keyed: Point { y: 2, x: 1 } is valid, and
Point { ..base, x: 3 } copies the fields not named explicitly. A binding
must be var to assign through one of its fields.
Variant constructors can use the type name (Shape.Dot(point)) or a leading
dot when the expected enum type is known (.Dot(point)). Match patterns use
the same tuple or record shape as their variant.
Traits and implementations
A trait lists required methods and associated types. impl Trait for Type
supplies that contract; impl Type declares inherent methods. Method calls
use dot syntax, while associated functions use the type name. Generic bounds
use T: Trait + Other; associated-type constraints use
Iterator<Item = T>. Longer constraints can follow the signature in a
where clause.
dyn Trait is a runtime trait object. It preserves the methods and ownership
capabilities declared by the trait; it is not implicitly cloneable or
sendable unless the trait contract establishes those properties.
Type aliases use type Name = ExistingType;. They give another spelling to
the same type rather than creating a new nominal type.
For the ownership behavior of records, enums, trait objects, and generic members, see ownership and sending.