首页 > 解决方案 > 从关闭返回时的 RefMut 生命周期错误

问题描述

我的结构中有一个RefCell要访问和修改的结构。但是,我可以访问它的唯一方法RefCell是使用闭包。因此,我想从闭包中返回一个可变引用( 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我返回的生命周期超过了我创建它的闭包的生命周期。

尽管如此,我还是看到了与我想要实现的功能类似的代码——例如这里

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参考,我缺少什么?

标签: rustlifetimerefcell

解决方案


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

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

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

  • 将您的结构更改为 haveRc<RefCell<_>>而不仅仅是RefCell<_>. 然后你可以Rc::clone(view.state_mut())从关闭中返回,然后再借用它。

  • 在关闭期间借用并进行更改。


推荐阅读