吸气剂中的可变借贷寿命不长

时间:2018-07-24 15:41:25

标签: rust borrow-checker

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 | |     }
   | |_____^

我不想公开data字段,因此我尝试使用吸气剂。我知道getter在Rust中不能很好地工作,并且正确封装的集合不应具有可变的get,但这是我从另一种语言移植的一些代码,因此我不会在该语言上执行任何重构。时刻(只需移植并覆盖测试)。那里的一生问题是什么?

1 个答案:

答案 0 :(得分:2)

使用

pub fn broken(&mut self) -> &mut Data {
    &mut self.foos.first_mut().unwrap().data_mut()
}

核心问题是data_mut()的返回类型已经是一个&mut Data值,因此您实际上是在创建一个&mut &mut Data,尽管这会崩溃。您遇到的最简单的解决方法是完全删除&mut

pub fn broken(&mut self) -> &mut Data {
    self.foos.first_mut().unwrap().data_mut()
}

似乎通过添加&mut导致借阅检查器创建了一个临时位置,然后引用了该位置。