1 error[E0308]: mismatched types
--> src/main.rs:166:3
|
162 | fn foo<F>() -> F
| - -
| | |
| | expected `F` because of return type
| | help: consider using an impl return type: `impl FnMut() -> PathBuf`
| expected this type parameter
...
166 | || PathBuf::new()
| ^^^^^^^^^^^^^^^^^ expected type parameter `F`, found closure
|
= note: expected type parameter `F`
found closure `{closure@src/main.rs:166:3: 166:5}`
= help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F`
I'm unable to wrap my brain around the final part: "every closure has a distinct type and so could not always match the caller-chosen type of parameter F".
Is it, in a roundabout way, hinting at "If you could use a generic, you could specify the type using foo::<SomeTime>(), but each closure is unique so we're not even going to give you an opportunity to try to do so"?
Not really, it's not about denying the possibility. It's about who gets to choose the type:
Callers get to choose the type of generic parameters
Callee gets to choose the type of -> impl Trait
Forget closures for a second and consider this:
fn foo<S: std::fmt::Display>() -> S {
"hi!"
}
error[E0308]: mismatched types
--> src/lib.rs:3:5
|
2 | fn foo<S: std::fmt::Display>() -> S {
| - -
| | |
| | expected `S` because of return type
| | help: consider using an impl return type: `impl std::fmt::Display`
| expected this type parameter
3 | "hi!"
| ^^^^^ expected type parameter `S`, found `&str`
|
= note: expected type parameter `S`
found reference `&'static str`
= note: the caller chooses a type for `S` which can be different from `&'static str`
The API says "for whatever S you, the caller, choose, I will return an S -- provided S implements Display". But then you went and tried to return a &str, instead of whatever the caller chose.
The solution is to put the choice in your (the callee's) hands.
fn foo() -> impl std::fmt::Display {
"hi!"
}
And it's no different for closure types. If you (the callee) are returning one specific closure, a generic parameter is the wrong tool.
(Note also that the caller can "choose" not just by turbofish, but by context -- calling the function in some position where a specific output type is expected, say.)