Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

rust - Mutable borrow in a getter not living long enough

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...