Skip to content

Traits & Extend

trait describes capabilities a type must provide. Use traits to constrain generics and organize shared APIs. A trait is not a normal value type.

Empty traits can be declared with a semicolon:

trait Numeric;

Traits with required methods use a body:

trait Equatable {
static Bool equal(Self& lhs, Self& rhs);
}
trait Hashable: Equatable {
UInt64 hash();
}

Non-static required methods use the current type as the receiver. static required methods do not have self.

Types can list traits in their declaration and provide matching methods:

trait HasValue {
Int value();
}
struct Box: HasValue {
Int inner;
Int value() {
return self.inner;
}
}

extend adds methods or a trait implementation after the type declaration:

struct User {
Int id;
}
extend User {
Int id_value() {
return self.id;
}
}
extend User: HasValue {
Int value() {
return self.id;
}
}

extend members follow member_decl; init and deinit are not member declarations.

trait Iterable {
associated Item;
Item item();
}

Associated types can have bounds:

trait HasItem {
associated Item: Hashable & Equatable;
Item item();
}

Implementations bind associated types:

struct Counter: Iterable {
associated Item = UInt8;
UInt8 item() {
return 42;
}
}

extend can bind them too:

struct RangeCounter {}
extend RangeCounter: Iterable {
associated Item = Int;
Int item() {
return 0;
}
}

Use a qualified associated type path when multiple traits expose the same associated name:

trait Left {
associated Item;
Item left();
}
trait Right {
associated Item;
Item right();
}
struct Pair: Left, Right {
associated Left.Item = UInt8;
associated Right.Item = Int;
UInt8 left() {
return 20;
}
Int right() {
return 22;
}
}
@where(T: Hashable & Equatable)
UInt hash_key<T>(T value);

Associated type binding:

@where(T: Iterable<Item = UInt8>)
Int count<T>(T value);

Projected equality:

@where(T.[Iterable].Item == UInt8)
Int count_bytes<T>(T value);

The prelude provides common trait and bound names such as:

  • Numeric
  • Mutable
  • Hashable
  • Equatable
  • FromStringLiteral
  • SubscriptGet / SubscriptSet

Subscript traits can model value[index]:

public trait SubscriptGet {
associated Index: Equatable;
associated Value;
Value subscript_get(Index index);
}
public trait SubscriptSet: SubscriptGet {
() subscript_set(Index index, Value value);
}