Generic Types
Cyrus supports generic types to create reusable and flexible type constructs. Generics are compile-time constructs, enabling static dispatch. They can be applied to enums, structs, unions, and type aliases.
1. Generic Type Constructs
1.1 Generic Enums
enum Result<V, E = bool> {
Ok(V),
Err(E),
}
VandEare generic type parameters.Ehas a default type, allowing omission during instantiation:
var r1 = Result.Ok<int>(10); // V=int, E=bool (default)
var r2 = Result.Ok<int, string>(10); // V=int, E=string
1.2 Generic Structs
struct Pair<A, B> {
first: A,
second: B,
}
var p = Pair<int, string> { first: 42, second: "hello" };
- Type arguments can be explicit or inferred from context:
var q: Pair<float, float> = Pair { first: 3.14, second: 2.71 };
1.3 Generic Unions
union ValueOrError<T> {
Value(T),
Error(string),
}
var v = ValueOrError.Value<int>(100);
- Works like enums but allows single-value variants.
1.4 Type Aliases with Generics
type Foo<X, Y> = Pair<Y, X>;
- Reorders generic parameters from the original type.
- Example usage:
var f: Foo<int, string> = Foo { first: "hello", second: 42 };
// Foo<int, string> = Pair<string, int>
- Defaults can be used:
type DefaultPair<A> = Pair<A, bool>;
fn main() {
var d: DefaultPair<int> = DefaultPair { first: 10, second: true };
}
2. Positional and Named Type Arguments
2.1 Positional
var r1 = Result.Ok<int>(10); // V=int, E=bool (default)
var r2 = Result.Ok<int, string>(10); // V=int, E=string
2.2 Named
var r3 = Result.Ok<E = string, V = int>(10);
- Named arguments override defaults regardless of order.
- Mix positional and named arguments as needed.
3. Generic Type Inference
var r4: Result<float> = Result.Ok(3.14); // V=float, E=bool (default)
Compiler resolution order:
- Explicit type arguments
- Defaults
- Expected type context
If inference fails, the compiler reports an error and requires explicit type arguments.
4. Combined Example
struct Pair<A, B> { first: A, second: B }
type Swap<X, Y> = Pair<Y, X>
enum Result<V, E = string> { Ok(V), Err(E) }
var p: Swap<int, string> = Swap { first: "hi", second: 42 }
var r: Result<float> = Result.Ok(3.14)
var r2: Result<float, bool> = Result.Err(false)
Swap<int, string>=Pair<string, int>Result<float>uses defaultE=string
5. Compile-Time vs Runtime
Generic types in Cyrus are compile-time constructs, also known as static dispatch.
- Code for each concrete instantiation is generated at compile time.
- No runtime type checks for generics.
- High performance, as calls are monomorphized.
6. Runtime Polymorphism (Uncompleted)
- Cyrus also supports runtime polymorphism via other mechanisms (interfaces or trait-like structures, in progress).
- Generic types are not runtime-polymorphic; they remain static.
7. Generic Functions (Uncompleted)
- Cyrus supports generic functions, similar to generic types.
- Placeholders:
fn identity<T>(value: T) T {
return value;
}

