rust 为什么我会得到一个“闭包实现了'FnMut',所以对捕获变量的引用不能转义闭包”?

3z6pesqy  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(140)

我有一个通用的Interface特征。Interface有一个method,它将被动态调度调用。具体来说,我将传递Rc<RefCell<dyn Interface>>
我有一个用例,我需要将对method的调用 Package 在闭包中。期望的行为是,用input调用闭包将等同于用input调用obj.method,其中obj实现Interface
以下是我迄今为止的尝试。

use std::cell::RefCell;
use std::rc::Rc;

pub trait Interface<'p, T> {
    fn method<'s: 'p>(&'p self, input: &'s str) -> T;
}

fn wrap_interface_with_closure<'p, 's: 'p, T: 'p>(
    instance: Rc<RefCell<dyn Interface<'p, T>>>,
) -> impl FnMut(&'s str) -> T + 'p {
    move |input| (*instance).borrow().method(input)
}

这会产生以下错误:

error[E0716]: temporary value dropped while borrowed
   |
13 |     instance: Rc<RefCell<dyn Interface<'p, T>>>,
   |     -------- lifetime `'2` appears in the type of `instance`
14 | ) -> impl FnMut(&'s str) -> T + 'p {
15 |     move |input| (*instance).borrow().method(input)
   |                  ^^^^^^^^^^^^^^^^^^^^--------------
   |                  |                                |
   |                  |                                temporary value is freed at the end of this statement
   |                  creates a temporary which is freed while still in use
   |                  argument requires that borrow lasts for `'2`

error: lifetime may not live long enough
   |
13 |     instance: Rc<RefCell<dyn Interface<'p, T>>>,
   |     -------- lifetime `'2` appears in the type of `instance`
14 | ) -> impl FnMut(&'s str) -> T + 'p {
15 |     move |input| (*instance).borrow().method(input)
   |     ------------   ^^^^^^^^ closure capture requires that `'1` must outlive `'2`
   |     |
   |     lifetime `'1` represents this closure's body
   |
   = note: closure implements `FnMut`, so references to captured variables can't escape the closure

error: aborting due to 2 previous errors; 2 warnings emitted

当它说closure implements FnMut, so references to captured variables can't escape the closure时,它指的是哪个被捕获的变量?它是说instance正在转义吗?它是否意味着借位正在转义?

new9mtju

new9mtju1#

你的特征需要&'p self,也就是说,对self的引用必须和'p相同。在闭包中,你调用borrow()

(*instance).borrow()

你获得了一个对接口的引用,它的生存期只持续到闭包('1),但是,你的特征定义要求self的生存期为'p

fn method<'s: 'p>(&'p self, input: &'s str) -> T;

因此,当你在闭包中调用.method()时,self的生存期将是'1(在闭包中有效),它的生存期不足以满足你的参数'p的生存期。你可以通过删除self的要求来解决这个问题:

fn method<'s: 'p>(&self, input: &'s str) -> T;

您仍然可以确定input的寿命比instance长,因为's :'pwrap_interface_with_closure函数的一部分。

相关问题