Las cotas de trait (trait bounds) restringen parámetros de tipo genérico para que una función pueda llamar métodos de trait sobre valores de tipo desconocido. La sintaxis <T: TraitName> significa "esta función funciona para cualquier tipo T que implemente TraitName".
// Trait bounds: función genérica que acepta cualquier tipo con Display trait Display { fn to_string(self) -> String } struct Point { x: int, y: int } impl Display for Point { fn to_string(self) -> String { return "(" + int_to_string(self.x) + ", " + int_to_string(self.y) + ")" } } struct Circle { radius: int } impl Display for Circle { fn to_string(self) -> String { return "Circulo{radio=" + int_to_string(self.radius) + "}" } } fn print_it<T: Display>(x: T) -> String { return x.to_string() } fn show_twice<T: Display>(x: T) { let s: String = x.to_string() print(s) print(s) } fn main() -> int { let p: Point = Point { x: 7, y: 2 } print(print_it<Point>(p)) let c: Circle = Circle { radius: 10 } print(print_it<Circle>(c)) show_twice<Point>(p) return 0 }
(7, 2)
Circulo{radio=10}
(7, 2)
(7, 2)Cómo funciona
print_it<T: Display> es una función genérica que acepta cualquier tipo T siempre que implemente Display. La cota T: Display le indica al compilador dos cosas: que puede generar una versión especializada para cada tipo concreto usado en el sitio de la llamada (monomorfización), y que garantiza que x.to_string() siempre es una llamada válida dentro del cuerpo de la función.
show_twice demuestra que los genéricos con cota de trait son funciones ordinarias — pueden tener variables locales, llamar al método del trait varias veces y producir cualquier efecto secundario. El compilador produce versiones de código máquina separadas para Point y cualquier otro tipo que le pases, así que no hay sobrecarga de despacho virtual.
En el sitio de la llamada, el argumento de tipo se escribe explícitamente como print_it<Point>(p). Nyx a menudo puede inferir el argumento de tipo, pero ser explícito siempre es válido y a veces resulta más claro al leer el código.