impl Trait is Rust syntax for using a type through the trait or traits it implements, without writing a named type parameter. It works like regular generics in many cases, but the function controls the concrete type rather than the caller. section 12.2 section 12.2.1
Use the syntax with these boundaries in mind:
- Write bounds directly, as in `input: impl Display`, when a function accepts any type implementing the named trait. section 12.2.1
- Treat two separate `impl Trait` parameters as potentially different types; use a named generic type when both arguments must be the same type. section 12.2.1
- Use impl Trait only as a regular function parameter or return type; not in trait implementations, let bindings, or type aliases. section 12.2.1
Returning a closure
A function can return an unnamed closure by describing its callable trait and signature: `fn returns_a_closure(input: &str) -> impl FnMut(i32) -> i32`. Different branches can return closures with different concrete types because the return type hides those details, while every branch must satisfy `FnMut(i32) -> i32`. Calling the returned closures can then double, triple, or leave a number unchanged. section 12.2.2
fn returns_a_closure(input: &str) -> impl FnMut(i32) -> i32 {
match input {
"double" => |mut number| {
number *= 2;
println!("Doubling number. Now it is {number}");
number
},
"triple" => |mut number| {
number *= 3;
println!("Tripling number. Now it is {number}");
number
},
_ => |number| {
println!("Sorry, it's the same: {number}.");
number
},
}
}
fn main() {
let my_number = 10;
let mut doubles = returns_a_closure("double"); #1
let mut triples = returns_a_closure("triple"); #1
let mut does_nothing = returns_a_closure("HI"); #1
let doubled = doubles(my_number);
let tripled = triples(my_number);
let same = does_nothing(my_number);
}
Inspect a complete runnable example that selects and invokes closures returned through impl Trait. section 12.2.2
