【问题标题】:RefMut lifetime error when returning from closure从关闭返回时的 RefMut 生命周期错误
【发布时间】:2021-01-11 23:17:00
【问题描述】:

我的结构中有一个RefCell,我想访问和修改它。但是,我可以访问此RefCell 的唯一方法是使用闭包。因此,我想从闭包中返回一个mutable reference (RefMut),我可以在封闭范围内使用和修改它。

{
    let mut state_ref: RefMut<_> = self.dialog.call_on_name("dirview", |view: &mut Canvas<RefCell<FileDialogState>>| {
        let state: &RefCell<FileDialogState> = view.state_mut();
        state.borrow_mut()
    }).unwrap();

    state_ref.foo = bar;

    // Mutable reference to RefCell should cease to exist here
}

但是,编译器抱怨我返回的 RefMut 超过了我创建它的闭包的生命周期。

尽管如此,我看到的代码与我想要实现的目标类似——例如here:

impl Backend {
    pub fn init() -> ... {
        let stdout = RefCell::new(BufWriter::new(io::stdout()));
        ...
    }

    fn stdout_mut(&self) -> RefMut<BufWriter<Stdout>> {
        self.stdout.borrow_mut()
    }

这两个用例有什么区别?为了能够返回 RefMut 引用,我缺少什么?

【问题讨论】:

    标签: rust lifetime refcell


    【解决方案1】:

    RefCell 动态检查共享可变访问,但它动态地管理整个单元格的所有权(这是Rc 之类的工作)。 RefRefMut 仅在底层 RefCell 存在时才有效,这就是为什么您不能从此闭包中返回 RefMut:该代码的结构中不能保证 @987654327 @ 将继续存在。 (如果.state_mut() 的类型为返回的引用指定了足够长的生命周期,则可能存在,但显然没有。)

    在第二种情况下,stdout_mut 省略了生命周期,它将返回的 RefMut 的生命周期参数链接到 &amp;self 的生命周期,这提供了必要的保证。 (如果您将 lint 设置更改为 #[warn(elided_lifetimes_in_paths)],那么每当用户定义类型中的生命周期参数被省略时,您都会收到警告,这有助于使这一点更清晰。)

    要在第一种情况下解决您的问题,您可以:

    • 将您的结构更改为具有Rc&lt;RefCell&lt;_&gt;&gt; 而不仅仅是RefCell&lt;_&gt;。然后你可以从闭包中返回Rc::clone(view.state_mut()),然后借用它。

    • 在闭包中借用并进行更改。

    【讨论】:

      猜你喜欢
      • 2018-09-09
      • 2013-02-06
      • 2012-03-16
      • 1970-01-01
      • 2017-05-03
      • 2013-11-26
      • 2017-12-27
      • 2014-09-10
      • 2013-02-23
      相关资源
      最近更新 更多