That’s not the case, took me a minute to realize though. The important point is polymorphism. A closure like |x| x
will have some anonymous closure type, lets call it MyClosure
such that you get an (automatically created) impl<A> Fn<(A,)> for MyClosure
. see edit below
Regarding your original question about associated vs parameter type: As the example of Into
shows, this is actually a thing that could be designed in different ways. Since the main application is closures which can (by polymorphism) allow different argument types but always have a result type that’s determined by their arguments, an approach of making the trait allow as little freedom as necessary leads to the return type being an associated type. Furthermore, it might help with type inference. see edit below
I was going to make a comparison of closures with normal functions claiming they work the same in this regard, but actually they don’t. I came up with this example which makes me even question if having the return type be an associated type in the Fn
-traits really is the best way.
fn f<A>() -> A { unimplemented!() }
fn apply<A,F: FnOnce() -> A>(f: F) -> A { f() }
pub fn foo() {
let g = || unimplemented!();
let _ = apply::<String,_>(f);
let _ = apply::<(),_>(f);
// only one of these works at a time!
let _ = apply::<String,_>(g);
//let _ = apply::<(),_>(g);
}
(playground)
Edit: Apparently closures don’t offer any polymorphism either...
fn foo() {
let f = |x| x;
f(1);
f("hi");
}
(playground)
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/lib.rs:5:7
|
5 | f("hi");
| ^^^^ expected integer, found `&str`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
Edit2: I just had the idea that a need for the arguments being type parameters probably comes from the fact that closures can be polymorphic over lifetimes. In the way that
Fn(&str) -> &str
actually means
for<'a> Fn<(&'a str,), Output = &'a str>