8.14 Type Inference for Function Return Types
Rust’s type inference capabilities are powerful for local variables (let x = 5;
infers x
is i32
), but function signatures generally require explicit type annotations for both parameters and return types.
// Requires explicit parameter types and return type.
fn add(a: i32, b: i32) -> i32 {
a + b
}
One notable exception is when using impl Trait
in the return position. This syntax allows you to specify that the function returns some concrete type that implements a particular trait, without having to write out the potentially complex or unnameable concrete type itself (especially useful with closures or iterators).
// This function returns a closure. The exact type of a closure is unnameable. // 'impl Fn(i32) -> i32' means "returns some type that implements this closure trait". fn make_adder(x: i32) -> impl Fn(i32) -> i32 { // The closure captures 'x' from its environment. move |y| x + y } fn main() { let add_five = make_adder(5); // add_five holds the returned closure. println!("Result of add_five(10): {}", add_five(10)); // Output: 15 let add_ten = make_adder(10); println!("Result of add_ten(7): {}", add_ten(7)); // Output: 17 }
While impl Trait
provides some return type inference flexibility, you still must explicitly declare the trait(s) the returned type implements. Full return type inference like in some functional languages is generally not supported to maintain clarity and aid compile-time analysis.