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();
}
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.
I'll try to give a more thorough answer: the issue has to do with the definition of the
accounts
member ofAccounts
.Vec<Box<Account>>
in this context is equivalent toVec<Box<Account + 'static>>
, i.e. the box can't contain any references to data on the stack. On the other hand, the declaration ofadd_account
doesn't restrict the lifetime of the type: it's equivalent tofn 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:
At this point, though, you have a data structure which is probably more general than you actually need.
The compiler's suggestion actually works. If you write
add_account
as follows:your code compiles. (Incidentally, you need
&mut self
, not&self
here)