Search code examples
rustrust-tokio

Rust Dummy Future Value?


I have a use case where I need to specify a dummy Future to make a type concrete. The use case is I have a struct which takes a generic parameter, which is a Future:

let thing = Thing<Fut>::some_method().await?;

some_method is a method on Thing which does not use the Fut at all, but the compiler complains because of the compiler limitations such that the type can't be inferred and is necessary because of the async block.

Since I need a concrete sized thing for Fut, I was hoping there was something in futures_util that I could use. Right now, this is my very bad approach:

use futures::Future;
use std::pin::Pin;

struct Thing<Fut>
where
    for<'b> Fut: Future<Output = ()> + Send + 'b,
{
    callback: dyn Fn() -> Fut + Send + Sync,
}

impl<Fut> Thing<Fut> where for<'b> Fut: Future<Output = ()> + Send + 'b {
    async fn some_method(a: i32) -> Result<(), Box<dyn std::error::Error>> {
        println!("I am some_method with value {}", a);
        Ok(())
    }
}

struct Dummy {
}

impl Future for Dummy {
    type Output = ();
        fn poll(
        self: Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Self::Output> {
        unimplemented!()
    }
}

#[tokio::main]
async fn main() {
    // this fails
    Thing::some_method(3).await.unwrap();
    
    // this works
    //Thing::<Dummy>::some_method(3).await.unwrap();
}

Is there something I can leverage here to make such a dummy value available?

Here is a minimal playground example: playground link

The error:

error[E0698]: type inside `async` block must be known in this context
  --> src/main.rs:33:5
   |
33 |     Thing::some_method(3).await.unwrap();
   |     ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Fut`
   |
note: the type is part of the `async` block because of this `await`
  --> src/main.rs:33:26
   |
33 |     Thing::some_method(3).await.unwrap();
   |                          ^^^^^^

If you uncomment the success line, it will remove the error.


Solution

  • You can use std::future::Ready (or probably Pending alternatively). This is the type returned by the std::future::ready function.

    use std::future::Ready;
    
    type Dummy = Ready<()>;
    
    #[tokio::main]
    async fn main() {
        Thing::<Dummy>::some_method(3).await.unwrap();
    }
    

    But if this function has no dependence on Fut, then I'd question why it's an associated function on Thing in the first place. Maybe it should be a free-standing function instead.