【问题标题】:Mutable borrow in a getter not living long enough吸气剂中的可变借用寿命不够长
【发布时间】:2018-07-24 15:41:24
【问题描述】:
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。我知道 getter 在 Rust 中不能很好地工作,并且正确封装的集合不应该有一个可变的get,但这是我从另一种语言移植的一些代码,所以我现在没有执行任何重构(只是移植和覆盖测试)。那里的寿命问题是什么?

【问题讨论】:

  • 我觉得这个问题很有趣,但我认为代码可以最小化。
  • @Boiethios 最小复制:play.rust-lang.org/… 我还认为 NLL 会修复此代码。
  • 我不知道它是否适用于您的原始较大代码,但您的游乐场示例中的问题是您不需要&amp;mut,因为data_mut 已经返回@987654330 @。 play.rust-lang.org/…
  • 天哪。 掌心。是的,这行得通。我习惯于在字段引用前加上 &amp;mut ,并在 getter 返回前加上前缀。等待将您的答案标记为答案
  • 所以,据我所知,getter 正在向调用者返回正确的引用。使用 &amp;mut 前缀结果导致该结果成为临时结果,并且代码试图返回对该临时结果的引用,这在技术上是正确的,因为强制

标签: rust borrow-checker


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    相关资源
    最近更新 更多