I am using the following code and am trying to understand why the part that is commented out is not able to compile. I would think Rust is able to infer the argument to the closure (x) given it could only ever be MyStruct. I am also wondering if anyone has any workarounds which would make it automatically infer this type.
My goal is to allow both synchronous and asynchronous functions to be defined by the user of my library while also inferring the first closure's argument from another part of the library, which I have not included here to make the demonstration simpler but I could include a more verbose example if helpful.
Any help would be greatly appreciated!
use std::{future::Future, pin::Pin};
pub struct MyStruct {
pub name: String,
}
// The marker system is modelled after: https://geo-ant.github.io/blog/2021/rust-traits-and-variadic-functions/
pub trait MyTrait<TMarker> {
fn exec(self, x: MyStruct) -> Pin<Box<dyn Future<Output = String>>>;
}
pub struct Marker1;
impl<TFuture: Future<Output = String> + 'static, TFunc: Fn(MyStruct) -> TFuture> MyTrait<Marker1>
for TFunc
{
fn exec(self, x: MyStruct) -> Pin<Box<dyn Future<Output = String>>> {
Box::pin(self(x))
}
}
pub struct Marker2;
impl<TFunc: Fn(MyStruct) -> String + 'static> MyTrait<Marker2> for TFunc {
fn exec(self, x: MyStruct) -> Pin<Box<dyn Future<Output = String>>> {
Box::pin(async move { self(x) })
}
}
fn my_func<TMarker>(func: impl MyTrait<TMarker>) -> Pin<Box<dyn Future<Output = String>>> {
func.exec(MyStruct {
name: "Hello World".to_string(),
})
}
#[tokio::main]
async fn main() {
// This compiles
println!(
"{}",
my_func(|x: MyStruct| async move { format!("String: {}", x.name) }).await
);
println!(
"{}",
my_func(|x: MyStruct| format!("String: {}", x.name)).await
);
// I would expect this to compile
// println!("{}", my_func(|x| async move { format!("String: {}", x.name) }).await);
// println!("{}", my_func(|x| format!("String: {}", x.name)).await);
}
Update: Smaller reproduction of error