I'd like to curry this function that I will pass to another function to do work.
Here is an example.
fn find_by_name_cur<F>(conn: String) -> impl FnOnce(String) -> F
where
F: Future<Output = Option<Item>>,
{
move |name: String| async {
println!(
"fetching item by name: {} with connection: {}",
name.clone(),
conn.clone()
);
None
}
}
I'm getting an error
error[E0308]: mismatched types
--> src/main.rs:19:25
|
15 | fn find_by_name_cur<F>(conn: String) -> impl FnOnce(String) -> F
| - this type parameter
...
19 | move |name: String| async {
| _________________________^
20 | | println!(
21 | | "fetching item by name: {} with connection: {}",
22 | | name.clone(),
... |
25 | | None
26 | | }
| |_____^ expected type parameter `F`, found opaque type
|
= note: expected type parameter `F`
found opaque type `impl Future`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
I'm not fully understanding what's going on here. I've also tried to implement this as a trait where the struct contains the connection info and the final function signature is String -> Future<Option<Item>> but that also didn't work.
Here F is a type parameter. That means the caller can choose it freely. That's obviously incorrect: the return type depends on the implementation of your function, the caller can't choose it.
Consider the following function, which also fails to compile:
fn printable<T>() -> T
where
T: Display,
{
"something"
}
"something" is a &str which does implement Display, so why doesn't this compile? Well, the reason is the same: T can be anything the caller chooses, so what if someone were to call this like printable::<u32>()? That wouldn't work.
Cool, I was hoping there would be a way to do this on stable without going nightly. I actually saw this solution on Stack Overflow. Thanks a lot for your help!
error[E0277]: the size for values of type `(dyn Future<Output = Option<Item>> + 'static)` cannot be known at compilation time
--> src/main.rs:17:25
|
17 | move |name: String| async {
| ^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = Option<Item>> + 'static)`
= note: the return type of a function must have a statically known size
dyn Trait is unsized, so if you want to return it by value, you have to box it: the return type should be BoxFuture<Option<Item>>, and you should wrap the async block in Box::pin(…).