Kevin
Kevin

Reputation: 3368

How to specify lifetimes for `One type is more general then the other` compile error?

I have the following setup where I am trying to create a Dummy future which is intended to modify the values in-place inside the future obtained from f: FnMut(&mut i32) -> Fut. I am passing the generic function fun to substitute it, but I am getting different lifetimes.

#![allow(unused_variables)]

pub struct Dummy<Fut, F> {
    f: F,
    futures: futures::stream::FuturesUnordered<Fut>
}


impl<Fut, F> Dummy<Fut, F>
where
    F: FnMut(&mut i32) -> Fut,
    Fut: futures::Future<Output = ()>,
{
    fn new(f: F) -> Self {
        Self { 
            f,
            futures: futures::stream::FuturesUnordered::new()
        }
    }
}

impl<Fut, F> futures::Future for Dummy<Fut, F>
where 
    F: FnMut(&mut i32) -> Fut,
    Fut: futures::Future<Output = ()>
{
    type Output = ();
    
    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<()> {
        // logic emitted
        core::task::Poll::Ready(())
    }
    
}


fn fun<'a>(f: &'a mut i32) -> impl futures::Future<Output = ()> + 'a {
    async move {
        *f += 1;
    }
}

#[tokio::main]
async fn main() {
    Dummy::new(fun).await;
}

playground link

which gives the compile-error:

error[E0308]: mismatched types
  --> src/main.rs:45:20
   |
45 |     Dummy::new(fun).await;
   |                    ^^^^^^ one type is more general than the other
   |
   = note: expected trait `for<'r> FnOnce<(&'r mut i32,)>`
              found trait `for<'a> FnOnce<(&'a mut i32,)>`
   = note: the lifetime requirement is introduced here

error[E0308]: mismatched types
  --> src/main.rs:45:20
   |
45 |     Dummy::new(fun).await;
   |                    ^^^^^^ one type is more general than the other
   |
   = note: expected trait `for<'r> FnOnce<(&'r mut i32,)>`
              found trait `for<'a> FnOnce<(&'a mut i32,)>`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 4 previous errors

Is it possible to annotate the impl in a way that removes these mismatched types error? I could annotate everything with 'static, as I have done here: playground link. But I was trying to avoid this solution since I want to mutually borrow dependent data in the future poll method.

Upvotes: 1

Views: 70

Answers (1)

user4815162342
user4815162342

Reputation: 155246

The signature of fun() connects the lifetime of the reference with the lifetime of the future it returns. You need to specify the same kind of connection on the Future implementation of Dummy:

impl<'a, Fut, F> futures::Future for Dummy<Fut, F>
where
    F: FnMut(&'a mut i32) -> Fut,
    Fut: futures::Future<Output = ()> + 'a,

Playground

Upvotes: 2

Related Questions