简体   繁体   中英

Why Rust complains about lifetime of types in functions that don't use instances of these types?

Rust requires lifetimes for types that don't have instances:

use futures::future::BoxFuture;

struct A{
    
}

impl A{

    async fn send_and_expect<T>(&mut self, unauthorized_retry: i32) -> std::result::Result<(),()>{
        Err(())        
    }
    
    fn send_and_expect_wrapper<'a, T>(&'a mut self, unauthorized_retry: i32) 
    -> BoxFuture<'a, std::result::Result<(),()>> {
        Box::pin(self.send_and_expect::<T>(unauthorized_retry))
    }
}

Error:

Standard Error

   Compiling playground v0.0.1 (/playground)
error[E0309]: the parameter type `T` may not live long enough
  --> src/lib.rs:15:9
   |
13 |     fn send_and_expect_wrapper<'a, T>(&'a mut self, unauthorized_retry: i32) 
   |                                    - help: consider adding an explicit lifetime bound...: `T: 'a`
14 |     -> BoxFuture<'a, std::result::Result<(),()>> {
15 |         Box::pin(self.send_and_expect::<T>(unauthorized_retry))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl futures::Future` will meet its required lifetime bounds

error: aborting due to previous error

For more information about this error, try `rustc --explain E0309`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

I have to do fn send_and_expect_wrapper<'a, T>(&'a mut self, unauthorized_retry: i32)

Is there a reason? I never use an instance of T so there are no concerns about lifetime.

The type check does checking on types . From its point of view, a value only does propagating it's type and triggering actions on the type (such as coercing). And in your example T is involved into unsized coercion with : 'a bound. Why? See how BoxFuture is declared

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a, Global>>;

Desugared and extremely minimized example would be like:

pub trait Future {}
struct Closure<'a, T> {
    receiver: &'a mut (),
    params: std::marker::PhantomData<T>,
}
impl<'a, T> Future for Closure<'a, T> {}
fn foo<'a, T>() {
    let x: *mut Closure<'a, T>;
    let coerced: *mut (dyn Future + 'a) = x;
}

This gives the same error[E0309] .

The point is in a type checking rule: U = dyn _ + 'a implies U: 'a . Or simply (dyn _ + 'a): 'a

Applying this to our example ( U = Closure<'a, T> ) we get Closure<'a, T>: 'a which implies the same bound should hold on the substitutions, ie 'a: 'a and T: 'a . But our environment (the foo fn signature) tells nothing about the T: 'a requirement, hence the error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM