⚠️ Current state:partial. Registry,TopTrait/TopImpl, unification-basedfind_impl, and impl-satisfies-trait are wired into the typechecker. Missing today: associated-type substitution in method bodies, where-clause supertraits, coherence checking. The surface and runtime guarantees described below may overstate current enforcement — cross-check withdocs/CAPABILITY-MATRIX.adocrow "Traits", and see CORE-04 indocs/TECH-DEBT.adocfor the remaining work.
Traits define shared behavior that types can implement. They enable polymorphism and code reuse.
- Defining Traits
- Implementing Traits
- Using Traits
- Associated Types
- Default Implementations
- Trait Bounds
- Coherence
- Standard Traits
trait Greet {
fn greet(self: &Self) -> String
}
trait Shape {
fn area(self: &Self) -> Float64
fn perimeter(self: &Self) -> Float64
fn contains(self: &Self, point: Point) -> Bool
}
trait Container[T] {
fn new() -> Self
fn add(self: &mut Self, item: T)
fn get(self: &Self, index: Int) -> Option[&T]
fn len(self: &Self) -> Int
}
struct Person {
name: String,
age: Int
}
impl Greet for Person {
fn greet(self: &Self) -> String {
"Hello, my name is " ++ self.name
}
}
let p = Person { name: "Alice", age: 30 }
p.greet() // "Hello, my name is Alice"
impl[T] Container[T] for Vec[T] {
fn new() -> Vec[T] {
Vec::empty()
}
fn add(self: &mut Vec[T], item: T) {
self.push(item)
}
fn get(self: &Vec[T], index: Int) -> Option[&T] {
if index < self.len() {
Some(&self.data[index])
} else {
None
}
}
fn len(self: &Vec[T]) -> Int {
self.data.len()
}
}
// Only implement Show for Option[T] when T: Show
impl[T: Show] Show for Option[T] {
fn show(self: &Self) -> String {
match self {
Some(x) -> "Some(" ++ x.show() ++ ")",
None -> "None"
}
}
}
let circle = Circle { radius: 5.0 }
let area = circle.area() // Uses Shape::area
let vec: Vec[Int] = Container::new()
vec.add(42) // Uses Container::add
// dyn Trait for runtime polymorphism
fn describe_shape(shape: &dyn Shape) -> String {
format("Area: {}, Perimeter: {}", shape.area(), shape.perimeter())
}
let shapes: Vec[Box[dyn Shape]] = vec![
Box::new(Circle { radius: 1.0 }),
Box::new(Rectangle { width: 2.0, height: 3.0 })
]
for shape in shapes {
println(describe_shape(&*shape))
}
fn describe_shape_generic[S: Shape](shape: &S) -> String {
format("Area: {}, Perimeter: {}", shape.area(), shape.perimeter())
}
// More efficient - no runtime dispatch
describe_shape_generic(&circle)
trait Iterator {
type Item
fn next(self: &mut Self) -> Option[Self::Item]
}
struct RangeIter {
current: Int,
end: Int
}
impl Iterator for RangeIter {
type Item = Int
fn next(self: &mut Self) -> Option[Int] {
if self.current < self.end {
let value = self.current
self.current += 1
Some(value)
} else {
None
}
}
}
fn sum_iter[I](iter: &mut I) -> I::Item
where
I: Iterator,
I::Item: Add + Default
{
let mut total = I::Item::default()
while let Some(x) = iter.next() {
total = total + x
}
total
}
trait Eq {
fn eq(self: &Self, other: &Self) -> Bool
// Default implementation using eq
fn ne(self: &Self, other: &Self) -> Bool {
!self.eq(other)
}
}
impl Eq for Int {
fn eq(self: &Int, other: &Int) -> Bool {
// Only need to implement eq, ne comes free
*self == *other
}
}
trait Animal {
fn speak(self: &Self) -> String
fn introduce(self: &Self) -> String {
"I am an animal that says: " ++ self.speak()
}
}
struct Dog { name: String }
impl Animal for Dog {
fn speak(self: &Self) -> String {
"Woof!"
}
// Override default
fn introduce(self: &Self) -> String {
"I am " ++ self.name ++ " and I say: " ++ self.speak()
}
}
fn print_value[T: Show](x: T) -{IO}-> Unit {
println(x.show())
}
fn process[T: Clone + Show + Eq](x: T) -> T {
let y = x.clone()
if x.eq(&y) {
println(x.show())
}
y
}
fn complex_function[A, B, C](a: A, b: B) -> C
where
A: Clone,
B: Into[A],
C: From[A] + Default,
A: Show
{
let converted: A = b.into()
println(converted.show())
C::from(converted)
}
fn apply_to_all[F](items: Vec[Int], f: F)
where
F: for['a] Fn(&'a Int) -> Int
{
for item in items {
f(&item)
}
}
// Ord requires Eq
trait Ord: Eq {
fn compare(self: &Self, other: &Self) -> Ordering
}
// Must implement both Eq and Ord
impl Eq for MyType { ... }
impl Ord for MyType { ... }
You can only implement a trait if either:
- The trait is defined in your crate, OR
- The type is defined in your crate
// OK: Your trait, external type
trait MyTrait { }
impl MyTrait for Vec[Int] { }
// OK: External trait, your type
struct MyType { }
impl Show for MyType { }
// ERROR: External trait, external type
// impl Show for Vec[Int] { } // Not allowed
// Implement for all types that satisfy a bound
impl[T: Show] Show for Vec[T] {
fn show(self: &Self) -> String {
let items = self.iter().map(|x| x.show()).join(", ")
"[" ++ items ++ "]"
}
}
trait Eq {
fn eq(self: &Self, other: &Self) -> Bool
}
trait Ord: Eq {
fn compare(self: &Self, other: &Self) -> Ordering
}
enum Ordering { Less, Equal, Greater }
trait From[T] {
fn from(value: T) -> Self
}
trait Into[T] {
fn into(self) -> T
}
// From implies Into
impl[T, U: From[T]] Into[U] for T {
fn into(self) -> U {
U::from(self)
}
}
trait Show {
fn show(self: &Self) -> String
}
trait Debug {
fn debug(self: &Self) -> String
}
trait Clone {
fn clone(self: &Self) -> Self
}
// Copy is a marker trait - types are bitwise-copyable
trait Copy: Clone { }
trait Default {
fn default() -> Self
}
impl Default for Int {
fn default() -> Int { 0 }
}
impl Default for String {
fn default() -> String { "" }
}
trait Hash {
fn hash(self: &Self, hasher: &mut Hasher)
}
trait Iterator {
type Item
fn next(self: &mut Self) -> Option[Self::Item]
}
trait IntoIterator {
type Item
type IntoIter: Iterator[Item = Self::Item]
fn into_iter(self) -> Self::IntoIter
}
Automatically implement common traits:
#[derive(Eq, Ord, Clone, Show, Hash, Default)]
struct Point {
x: Int,
y: Int
}
// Generates:
// impl Eq for Point { ... }
// impl Ord for Point { ... }
// impl Clone for Point { ... }
// impl Show for Point { ... }
// impl Hash for Point { ... }
// impl Default for Point { ... }
- Types - Type system overview
- Functions - Generic functions
- Standard Library - Standard traits