liveBook · Manning

Impl Trait

As explained in Learn Rust in a Month of Lunches

impl Trait is Rust syntax for specifying an opaque type constrained by one or more traits, with the concrete type selected by the compiler or function implementation.

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

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains syntax, type relationships, compiler failure, placement limits, and closure returns, but defers broader generic theory.
Examples
Demonstrates printable values, maximum comparison, compiler diagnostics, and closures that double, triple, or modify fear.
What it assumes
Assumes basic generics and closures, while reinforcing type parameters, trait bounds, and closure traits through examples.
What you can do after
Apply impl Trait to simplify function parameters, enforce trait bounds, and return callable closures with known signatures.
How it connects
Connects impl Trait to generics, trait bounds, closures, FnMut, PartialOrd, Display, and function return types.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.