问题
pub type Data = i32;
pub struct Foo {
data: Data,
}
impl Foo {
pub fn data_mut(&mut self) -> &mut Data {
&mut self.data
}
}
pub struct Context {
data: Data,
foos: Vec<Foo>,
}
impl Context {
pub fn broken(&mut self) -> &mut Data {
// What are the lifetimes here that make this version not work?
&mut self.foos.first_mut().unwrap().data_mut()
}
pub fn working(&mut self) -> &mut Data {
&mut self.foos.first_mut().unwrap().data
}
}
fn main() {}
(Playground)
error[E0597]: borrowed value does not live long enough
--> src/main.rs:21:14
|
21 | &mut self.foos.first_mut().unwrap().data_mut()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
22 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 19:5...
--> src/main.rs:19:5
|
19 | / pub fn broken(&mut self) -> &mut Data {
20 | | // What are the lifetimes here that make this version not work?
21 | | &mut self.foos.first_mut().unwrap().data_mut()
22 | | }
| |_____^
I didn't want to have the data
field public, so I tried to use a getter. I know getters are not working well in Rust, and properly encapsulated collection shouldn't have a mutable get
, but this is some code I'm porting from a different language, so I'm not performing any refactoring at the moment (just porting and covering with tests). What's the lifetime issue there?
回答1:
With
pub fn broken(&mut self) -> &mut Data {
&mut self.foos.first_mut().unwrap().data_mut()
}
the core issue is that the return type of data_mut()
is already a &mut Data
value, so you're essentially creating a &mut &mut Data
, though that will collapse. The simplest fix in your case is to drop the &mut
entirely
pub fn broken(&mut self) -> &mut Data {
self.foos.first_mut().unwrap().data_mut()
}
It would seem that by adding the &mut
you're causing the borrow checker to create a temporary location and then take a reference to that location.
来源:https://stackoverflow.com/questions/51502717/mutable-borrow-in-a-getter-not-living-long-enough