impl Trait for opaque return types

Marcus Chen Jan 2026
1 tab
use std::fmt::Display;

fn make_adder(x: i32) -> impl Fn(i32) -> i32 {
    move |y| x + y
}

fn format_value(val: i32) -> impl Display {
    format!("Value: {}", val)
}

fn main() {
    let add_five = make_adder(5);
    println!("{}", add_five(10));
    println!("{}", format_value(42));
}
1 file · rust Explain with highlit

impl Trait in return position lets you return a type that implements a trait without naming it. This is useful for closures, iterators, or futures where the concrete type is complex or unnameable. The caller only knows it implements the trait. I use impl Trait for iterator chains (impl Iterator<Item=T>), async functions (which return impl Future), and anywhere the concrete type is an implementation detail. It's more ergonomic than Box<dyn Trait> because there's no heap allocation or dynamic dispatch. The limitation is that you can only return one concrete type (no branching between types). For multiple types, use trait objects or enums.