impl Trait
De forma similar a los límites de traits, se puede usar la sintaxis impl Trait
en argumentos de funciones y valores devueltos:
use std::fmt::Display; fn get_x(name: impl Display) -> impl Display { format!("Hello {name}") } fn main() { let x = get_x("foo"); println!("{x}"); }
impl Trait
permite trabajar con tipos a los que no se les puede asignar un nombre.
La naturaleza de impl Trait
varía ligeramente según la posición.
-
En el caso de los parámetros,
impl Trait
es como un parámetro genérico anónimo con un límite de trait. -
En el caso de un tipo de resultado devuelto, significa que este es un tipo concreto que implementa el trait, sin nombrar el tipo. Esto puede ser útil cuando no quieres exponer el tipo concreto en una API pública.
La inferencia es más complicada en la posición de retorno. Una función que devuelve
impl Foo
elige el tipo concreto que devuelve, sin escribirlo en el código fuente. Una función que devuelve un tipo genérico comocollect<B>() -> B
puede devolver cualquier tipo que cumplaB
, y es posible que el llamador tenga que elegir uno, como conlet x: Vec<_> = foo.collect()
o con la sintaxis turbofish,foo.collect::<Vec<_>>()
.
Este ejemplo es fantástico porque usa impl Display
dos veces. Nos ayuda explicar que no hay nada que obligue a que sea el mismo tipo impl Display
. Si se utiliza un solo T: Display
, se aplicaría la restricción de que el tipo de entrada T
y el tipo de retorno T
son iguales. No funcionaría para esta función en concreto, ya que el tipo que esperamos como entrada probablemente no sea el que devuelve format!
. Si quisiéramos hacer lo mismo a través de la sintaxis : Display
, necesitaríamos dos parámetros genéricos independientes.