That line can be simplified to:
fn compose<T, F: Fn(T)->T>(f1: F, f2: F) -> F { fn compose<T, F: Fn(T)->T>(f1: F, f2: F) -> F { fn compose<T, F: Fn(T) -> T, G: Fn(T) -> T>(f: F, g: G) -> impl Fn(T) - > T
or: fn compose<T, F, G>(f: F, g: G) -> impl Fn(T) -> T
where F: Fn(T) -> T, G: Fn(T) -> Thttps://doc.rust-lang.org/nightly/std/iter/trait.Iterator.ht...
... and `impl Trait` exists to be able to have return types which are difficult, verbose, or impossible to name.
fn compose<T, F: Fn(T) -> T>(f1: F, f2: F) -> F
As far as I'm aware the only way to write a function like that is fn compose<T, F: Fn(T) -> T>(f1: F, f2: F) -> F {
f1
}
and even then you can only call it like this let clos = |x| 2 * x;
compose(clos, clos); compose(|x| x, |x| x)
because the closures have the same type.It's a fun little thing, and a good example of why impl Trait in argument position is a really nice addition to Rust, even though based on what we were originally excited about (impl Trait in return position for returning Iterators and other such things), the argument position form didn't seem so important.