Generics
Generic Structs
Structs can be parameterized with one or more type parameters:
struct Box<T> {
T value;
Box(T v) {
this.value = v;
}
public T get() {
return this.value;
}
}
i32 main() {
Box<i32> b = Box<i32>(42);
return b.get(); // 42
}Multiple Type Parameters
struct Pair<K, V> {
K key;
V value;
}
i32 main() {
Pair<i32, i32> p = { .key = 42, .value = 100 };
return p.key + p.value; // 142
}Monomorphization
Generics are monomorphized at compile time. Each unique instantiation (e.g., Box<i32>, Box<i64>) generates a separate struct and method set. There is no runtime cost.
Generic Enums
Enums also support generics:
enum optional<T> {
Empty(),
Value(T)
}
optional<i32> x = optional<i32>::Value(42);See Enums for more details.
Generic Constraints
Type parameters can be constrained with interfaces using where:
interface IValue {
i32 getValue();
}
struct Container<T> where T : IValue {
T item;
}Only types that implement IValue can be used as T. Types that don't satisfy the constraint produce a compile error:
struct MyItem : IValue {
i32 data;
i32 getValue() { return this.data; }
}
struct Plain { i32 x; }
Container<MyItem> ok = { .item = { .data = 42 } }; // ok
Container<Plain> err = { .item = { .x = 1 } }; // error: Plain does not implement IValueMultiple Constraints
A type parameter can require multiple interfaces:
interface IReadable {
i32 read();
}
interface IWritable {
void write(i32 val);
}
struct Store<T> where T : IReadable, IWritable {
T backend;
}T must implement both IReadable and IWritable. Implementing only one produces a compile error.
Constraints on Multiple Parameters
Use separate where clauses joined by ;:
interface IHashable {
i32 hash();
}
interface ISerializable {
i32 serialize();
}
struct Map<K, V> where K : IHashable; where V : ISerializable {
K key;
V value;
}Constraints on Enums
where clauses work on enums too:
interface IValue {
i32 getValue();
}
enum Wrapper<T> where T : IValue {
Some(T),
None()
}Constraints on Interfaces
Generic interfaces can constrain their own type parameters:
interface IEquatable {
i32 equals();
}
interface ISortable<T> where T : IEquatable {
void sort();
}Constraints with Implements
A struct can have both a where clause on its generic parameters and implement interfaces:
interface IContainer {
i32 size();
}
interface IValue {
i32 getValue();
}
struct TypedBox<T> where T : IValue : IContainer {
T item;
i32 count;
i32 size() { return this.count; }
}Nested Generics
Generic types can be nested as type arguments:
struct Pair<K, V> {
K key;
V value;
}
struct Wrapper<T> {
T data;
i32 id;
}
i32 main() {
Wrapper<Pair<i32, i32>> w;
return 0;
}Generic Return Types
Functions can return generic structs:
struct Pair<K, V> {
K key;
V value;
}
Pair<i32, i32> makePair(i32 k, i32 v) {
return { .key = k, .value = v };
}
i32 main() {
auto p = makePair(5, 10);
return p.key + p.value; // 15
}