Traits & macros
Trait definitions, impl for, and macro expansion.
trait Show {
fn show(self)
}
struct Counter {
value: i32
}
impl Show for Counter {
fn show(self) {
print(self.value)
}
}trait Show {
fn show(self) -> void
}
struct Counter {
value: i32
}
impl Show for Counter {
fn show(self) {
print(self.value)
}
}Macros are parsed and expanded in a dedicated compiler pass before typecheck.
Static vs dynamic dispatch
Static: impl Trait for Type — method calls on a concrete struct resolve to a mangled function at compile time.
Dynamic: dyn Trait trait objects — cast with value as dyn Trait, pass to functions taking dyn Trait, call methods through a vtable. Multi-method traits use per-method vtable slots; trait objects run a Drop thunk that frees heap-boxed data.
Multi-trait objects: dyn A + B (and optional + Send / + Sync auto bounds) use a combined vtable. The concrete type must implement every listed trait; methods are dispatched in trait order (first-wins on name clashes). See examples/trait_dyn_ab.ny and examples/dyn_multi_trait.ny.
Trait bounds: fn f<T: Trait>(x: T) — generic functions constrained by traits; validated when monomorphized. See examples/trait_bounds.ny.
trait Add {
fn add(self, other)
}
struct Counter {
value: i32
}
impl Add for Counter {
fn add(self, other) {
return self.value + other
}
}
fn via_dyn(g) {
return g.add(1)
}trait Add {
fn add(self, other: i32) -> i32
}
struct Counter {
value: i32
}
impl Add for Counter {
fn add(self, other: i32) -> i32 {
return self.value + other
}
}
fn via_dyn(g: dyn Add) -> i32 {
return g.add(1)
}Multi-trait example:
trait Add {
fn add(self, other)
}
trait Scale {
fn scale(self, k)
}
struct Counter {
value: i32
}
impl Add for Counter {
fn add(self, other) {
return self.value + other
}
}
impl Scale for Counter {
fn scale(self, k) {
return self.value * k
}
}
fn both(g) {
return g.add(1) + g.scale(2)
}
fn main() {
let c = Counter { value: 10 }
print(both(c as dyn Add + Scale))
}trait Add {
fn add(self, other: i32) -> i32
}
trait Scale {
fn scale(self, k: i32) -> i32
}
struct Counter {
value: i32
}
impl Add for Counter {
fn add(self, other: i32) -> i32 {
return self.value + other
}
}
impl Scale for Counter {
fn scale(self, k: i32) -> i32 {
return self.value * k
}
}
fn both(g: dyn Add + Scale) -> i32 {
return g.add(1) + g.scale(2)
}
fn main() -> void {
let c: Counter = Counter { value: 10 }
print(both(c as dyn Add + Scale))
}See examples/trait_dyn.ny, examples/trait_dyn_multi.ny, examples/trait_dyn_ab.ny, examples/dyn_multi_trait.ny, and tests/nyra/trait_dispatch_test.ny, trait_dyn_multi_test.ny.