【发布时间】:2019-12-12 07:09:32
【问题描述】:
我正在尝试为一个结构实现一个方法,该结构返回一个闭包move-捕获其成员之一。理由是该成员是Copy,因此闭包可以复制它并且不应该与结构生命周期相关联。但是,它不会编译。
我希望 Rust 不会坚持 copy 引用 &self ,并通过保持对结构的引用将闭包生命周期与结构生命周期联系起来。当它没有编译时,我预计错误消息中会出现这种情况,但是 - 有点令人惊讶 - 我不确定这是确切的问题。
限制闭包的匿名生命周期是函数生命周期,它是 &self 的生命周期,而不是 self 的生命周期。当我move 时,我真的不明白这是什么问题。
其实我有两个问题:
首先,为什么函数生命周期会限制我的闭包? (可能是对我这边的错误消息的误解,我很乐意指出)。
第二,如何强制结构成员的move 而不将其复制到temp 变量(就在返回闭包之前)并使用temp 在闭包内部(有效,但在我看来不优雅)。
这是我的代码的简化版本:
struct Struct {
member: usize
}
impl Struct {
fn func(&self) -> Box<dyn Fn(usize)->usize> {
Box::new(move |argument: usize| {
self.member + argument
})
}
}
fn main() {
let s = Struct { member: 4 };
println!("{}", s.func()(5));
}
这在编译时给出:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src\main.rs:7:18
|
7 | Box::new(move |argument: usize| {
| __________________^
8 | | self.member + argument
9 | | })
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
--> src\main.rs:6:5
|
6 | / fn func(&self) -> Box<dyn Fn(usize)->usize> {
7 | | Box::new(move |argument: usize| {
8 | | self.member + argument
9 | | })
10| | }
| |_____^
= note: ...so that the types are compatible:
expected &Struct
found &Struct
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::ops::Fn(usize) -> usize + 'static)>
found std::boxed::Box<dyn std::ops::Fn(usize) -> usize>
error: aborting due to previous error
【问题讨论】:
-
请注意,在闭包中使用
self.member将使用调用闭包时member的值,而使用临时变量将使用调用@987654335时的成员值@。这是一个很大的语义差异,编译器不允许更改它,只是为了避免添加一行代码来创建临时代码。 -
@mcarton 想一想:据我所知,Rust 所有权规则禁止对不可变引用的数据进行突变。这不能阻止两者之间的语义差异吗?无论如何,我明白了。但是我没有办法向
move会员本身发出信号吗?
标签: rust closures move-semantics lifetime borrowing