// `impl Trait` in argument position *is* a generic parameter -- that is Rust's // own desugaring, `fn f(x: impl T)` for `fn f(x: A)`. The bound is // dropped like any other bound, so what is left is a fresh parameter, and Nim // instantiates it structurally at the call site. // // In return position it is an opaque type instead: the caller cannot name it, // and there is no Nim equivalent, so that is still rejected. use core::fmt::Debug; trait Area { fn area(&self) -> i32; } struct Sq { side: i32, } struct Rect { w: i32, h: i32, } impl Area for Sq { fn area(&self) -> i32 { self.side * self.side } } impl Area for Rect { fn area(&self) -> i32 { self.w * self.h } } fn describe(shape: impl Area) -> i32 { shape.area() } fn twice(shape: impl Area) -> i32 { shape.area() * 2 } fn both(a: impl Area, b: impl Area) -> i32 { a.area() + b.area() } fn show(x: impl Debug) -> i32 { let _ = x; 1 } fn main() { println!("{}", describe(Sq { side: 4 })); println!("{}", describe(Rect { w: 3, h: 5 })); println!("{}", twice(Sq { side: 3 })); println!("{}", both(Sq { side: 2 }, Rect { w: 10, h: 10 })); println!("{}", show(7i32)); }