How to return a future combinator with `&self`

前端 未结 1 1307
时光取名叫无心
时光取名叫无心 2020-12-21 05:37

I have this piece of code using futures v0.1:

impl ArcService for (Box>, Box) {
    fn call(&self, req:         


        
相关标签:
1条回答
  • 2020-12-21 06:31

    How to return a future combinator with &self

    You return a future that refers to self like this:

    use futures::future::{self, FutureResult}; // 0.1.28
    
    struct Example {
        age: i32,
    }
    
    impl Example {
        fn make_a_future(&self) -> FutureResult<&Example, ()> {
            future::ok(self)
        }
    }
    

    As discussed in the Tokio documentation on returning futures, the easiest stable solution to returning a complicated future is a impl Trait. Note that we assign an explicit lifetime to self and use that in the returned value (via + 'a):

    use futures::{future, Future}; // 0.1.28
    
    struct Example {
        age: i32,
    }
    
    impl Example {
        fn make_a_future<'a>(&'a self) -> impl Future<Item = i32, Error = ()> + 'a {
            future::ok(self).map(|ex| ex.age + 1)
        }
    }
    

    Your real question is "how can I lie to the compiler and attempt to introduce memory unsafety into my program?"

    Box<SomeTrait + 'static> (or Box<SomeTrait> by itself) means that the trait object must not contain any references that do not last for the entire program. By definition, your Example struct has a shorter lifetime than that.

    This has nothing to do with futures. This is a fundamental Rust concept.

    There are many questions that ask the same thing in regards to threads, which have similar restrictions. A small sampling:

    • Lifetime of variables passed to a new thread
    • How do I use static lifetimes with threads?
    • The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want
    • Lifetime troubles sharing references between threads

    Like in those cases, you are attempting to share a reference to a variable with something that may exist after the variable is destroyed. Languages such as C or C++ would let you do this, only to have your program crash at a seemingly random point in time in the future when that variable is accessed after being freed. The crash is the good case, by the way; information leaks or code execution is also possible.

    Like the case for threads, you have to ensure that this doesn't happen. The easiest way is to move the variable into the future, not sharing it at all. Another option is to use something like an Arc around your variable, clone the Arc and hand the clone to the future.

    0 讨论(0)
提交回复
热议问题