Rust not able to infer closure argument type when implmenting trait on closure

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);
}

(Playground)

Update: Smaller reproduction of error

I am not sure if this is something you'd ever want to do. It is a known problem that Rust's type inference for closure arguments is a lot dicier than everywhere else (there are complex technical reasons). In general, users can be expected to provide closure argument types when the compiler complains.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.