Similar to C++‘s constrained return, Rust functions can use impl Trait to return an “abstract” return type. This Return Position-impl Trait enable us to return closures as unnamed type in Rust.

fn f(a: f32) -> impl Fn(f32) -> f32 {
  let x = heavy_calculation(a);  
  move |b| { x + b }
}

Similarly, the concrete type of iterators can get ugly really fast, so this feature can also be useful.

Return Position-impl Trait doesn't make the function generic

Unlike Argument Position-Impl Trait, Return Position-impl Trait just makes the return type opaque/unnamable.

For example, the following code would not work without boxing

fn returns_summarizable(switch: bool) -> impl Summary
{
  if switch {
    NewsArticle { ... }
  } else {
    Tweet { ... } // Can't return a different type!
  }
}

Difference from C++/D's returning voldemort type

Unlike languages like C++ and D, we can’t use the concrete types with Rust’s return position-impl trait.

For example, the following code will not compile because the compiler only know s2 as some type that implement Display, and we can’t use string method like .push_str on it.

use std::fmt::Display;
 
fn displayable<T: Display>(t: T) -> impl Display { t }
 
fn main() {
  let s = String::from("hello");
  let mut s2 = displayable(s);
  s2.push_str(" world");
  println!("{s2}");
}

References