TransWikia.com

Lifetime error using traits and async function on protobuffers

Stack Overflow Asked by Hèctor M.C. on December 29, 2020

I’m having some issues understanding lifetimes in Rust. It may also be the way I implement my design.

error[E0597]: `request` does not live long enough
  --> src/service/session/server.rs:25:23
   |
25 |         let msg_ref = request.get_ref();
   |                       ^^^^^^^ borrowed value does not live long enough
...
32 |         let body: Box<dyn Body> = Box::new(signup);
   |                                   ---------------- cast requires that `request` is borrowed for `'static`
...
44 |     }
   |     - `request` dropped here while still borrowed

The main source:

#[tonic::async_trait]
impl Session for SessionImplementation {
    async fn signup(
        &self,
        request: Request<SignupRequest>,
    ) -> Result<Response<SessionResponse>, Status> {
        let msg_ref = request.get_ref();
        let signup = TxSignup::new(&msg_ref.name, &msg_ref.addr, &msg_ref.pwd);

        let body: Box<dyn Body> = Box::new(signup);
        let tx = Transaction::new(body);
        let mut tx_signup: Box<dyn Tx> = Box::new(tx);
        tx_signup.execute();

        let response = SessionResponse {
            deadline: 0,
            cookie: "".to_string(),
            status: 0,
        };

        Ok(Response::new(response))
    }

    /* more code */
}

Background

The idea is to have a Transaction, that implements Tx { execute(&self), result(&self) ... };. This Transaction has a parameter body of the type Box<dyn Box>, being the trait Body { /*some fn*/ }. Having this, I’m pretending to implement some kind of hierarchy.

The code above

On line 24 I’m getting some requests of the type SignupRequest (from proto file). This is the implementation of proto’s server, using Tonic and Tokio.
After this, I have also an object TxSignup with some parameters of the type &str (set in from line 27 till 29). TxSignup implements the Body trait so I’m able to turn it into a Tx trait, apparently. The Transaction object wraps a Body implementation. I call the execute() function from the given trait Tx. All that explained has been done from line 32 till 35.

The problem

If I replace the &str type from TxSignup by type String it works. However, if I want them to be of the type &str, a lot of "incongruencies" with lifetimes emerge. I want it to be &str because none of these values will change. I think it is better to keep them on the stack instead of in the heap. Am I wrong?

If I want &str, I’m coerced to define TxSignup with <'a>, and here is where I get lost. I get why a lifetime is required, but not why all these problems appear.

As far I do understand, all elements inside the function should have the same lifetime, being killed at the end of its block (line 44). I will never send them outside.

I have tried giving to Body trait also an <'a>, and even to Tx trait (meaning the Transaction object must have one too to match the trait).

Is there any way to make it work? Am I misunderstanding the Trait use and how they work, or this patter design will never work?

Reproduction on GitHub

I have reproduced this same error in my rust-proto repository. Running cargo run should be enough.


I come from Go development and some C++, Java and Python, so I have a way of coding that may not be the most appropriate one using Rust. That’s what I want to solve.

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP