Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parameter type may not live long enough

Tags:

rust

I have a simple program where I am trying to implement a polymorphic account type:

enum AccountType {
    INVALID,
    TYPE1,
    TYPE2,
}

trait Account {
    fn get_name(&self) -> String;
    fn get_type(&self) -> AccountType;
}

struct Accounts {
    accounts: Vec<Box<Account>>,
}

impl Accounts {
    fn new() -> Accounts {
        let accs: Vec<Box<Account>> = Vec::new();
        Accounts { accounts: accs }
    }

    fn add_account<A: Account>(&self, account: A) {
        self.accounts.push(Box::new(account));
    }
}

fn main() {
    let accounts = Accounts::new();
}

(Rust Playground)

When I compile it, I see the following error:

error[E0310]: the parameter type `A` may not live long enough
  --> src/main.rs:23:28
   |
22 |     fn add_account<A: Account>(&self, account: A) {
   |                    -- help: consider adding an explicit lifetime bound `A: 'static`...
23 |         self.accounts.push(Box::new(account));
   |                            ^^^^^^^^^^^^^^^^^
   |
note: ...so that the type `A` will meet its required lifetime bounds
  --> src/main.rs:23:28
   |
23 |         self.accounts.push(Box::new(account));
   |                            ^^^^^^^^^^^^^^^^^

I have tried adding lifetimes to the type but could not find the right way to do it. Please let me know if this is not the right way to do polymorphism in Rust.

like image 263
russoue Avatar asked Oct 17 '25 08:10

russoue


1 Answers

I'll try to give a more thorough answer: the issue has to do with the definition of the accounts member of Accounts. Vec<Box<Account>> in this context is equivalent to Vec<Box<Account + 'static>>, i.e. the box can't contain any references to data on the stack. On the other hand, the declaration of add_account doesn't restrict the lifetime of the type: it's equivalent to fn add_account<'a, A: Account + 'a>(&self, account: A) {.

The solution is to make sure the type A lives long enough. The simplest approach is to just add the A: 'static bound suggested in the error message (fn add_account<A: Account + 'static>(&self, account: A) {).

If you don't want to copy the Account data, you can do something more complicated, like this:

struct Accounts<'a> {
    accounts: Vec<&'a Account + 'a>
}

impl<'a> Accounts<'a> {
    fn new() -> Accounts<'a> {
        Accounts { accounts: Vec::new() }
    }

    fn add_account<A: Account + 'a>(&mut self, account: &'a A) {
        self.accounts.push(Box::new(account));
    }
}

At this point, though, you have a data structure which is probably more general than you actually need.

like image 58
Eli Friedman Avatar answered Oct 20 '25 00:10

Eli Friedman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!