I'm trying to understand/solve the following error related to lifetimes (I'm new to rust so please bear with me).
The error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/tui/screens/accounts.rs:42:59
|
42 | self.account_table.items = state.eth_accounts.iter().map(|a| (a.get(), 0.0)).collect();
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 29:16...
--> src/tui/screens/accounts.rs:29:16
|
29 | state: &mut AppState,
| ^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/tui/screens/accounts.rs:42:40
|
42 | self.account_table.items = state.eth_accounts.iter().map(|a| (a.get(), 0.0)).collect();
| ^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 23:6...
--> src/tui/screens/accounts.rs:23:6
|
23 | impl<'a> Drawable for Accounts<'a> {
| ^^
note: ...so that the expression is assignable
--> src/tui/screens/accounts.rs:42:40
|
42 | self.account_table.items = state.eth_accounts.iter().map(|a| (a.get(), 0.0)).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Vec<(&'a str, _)>`
found `Vec<(&str, _)>`
So at a high level what I'm reading is: on line 42 I'm trying to assign something that has a lifetime mismatch between lefthand side and righthand side.
In particular, it seems that the righthand side contains a &str
with no lifetime parameter, while the lefthand side expects a &'a str
. Lefthand side makes total sense to me given I have a struct elsewhere in the code which looks like this:
pub struct StatefulTable<'a> {
pub state: TableState,
pub items: Vec<(&'a str, f64)>,
}
Now the righthand side is confusing. I think I get why there's no lifetime parameter there - it's because it's derived from state: &mut AppState
which also has no lifetime parameter. But beyond that I'm struggling with the below questions:
Question 1 - why can't rust automatically assign 'a to the &'str it gets back from the Hashmap's .get() method?
Like the compiler says at the end of the error message, it knows it wants a Vec<(&'a str, _)>
- so why not auto-assign 'a to the &str it gets from the hashmap?
Question 2 - why do both of the below attemps fail to solve the error?
I've tried manually massaging the righthand side into the appropriate format, but both of these fail:
self.account_table.items: Vec<(&'a str, f64)> = state.eth_accounts.iter().map(|a| (a.get(), 0.0)).collect();
self.account_table.items = state.eth_accounts.iter().map(|a| (a.get(), 0.0)).collect::<Vec<(&'a str, f64)>>();
Question 3 - what's the idiomatic way to solve this?
I basically have a global state without a lifetime parameter (line 29) and I'm trying to assign something from it to a local state with the 'a lifetime parameter. Should I:
- add 'a to global state? Feels excessive as I would have to go and mark up
<'a>
in most of the codebase. - use lifetime comparisons? If so, then how?
- somehow massage the anonymous lifetime into 'a? My 2 approaches above failed. Is there a third?
Hope this is specific/answerable enough. Lifetime errors are hard because they only arise when app gets complex enough and I always struggle to provide a "minimum reproducible example".