【发布时间】:2021-05-05 04:18:41
【问题描述】:
请考虑以下示例 (playground):
struct Animal<'a> {
format: &'a dyn Fn() -> (),
}
impl <'a>Animal<'a> {
pub fn set_formatter(&mut self, _fmt: &'a dyn Fn() -> ()) -> () {} // Getting rid of 'a here satisfies the compiler
pub fn bark(&self) {}
}
fn main() {
let mut dog: Animal = Animal { format: &|| {()} };
let x = 0;
dog.set_formatter(&|| {
println!("{}", x); // Commenting this out gets rid of the error. Why?
});
dog.bark(); // Commenting this out gets rid of the error. Why?
}
这会产生以下编译错误:
Compiling playground v0.0.1 (/playground)
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:13:24
|
13 | dog.set_formatter(&|| {
| ________________________^
14 | | println!("{}", x); // Commenting this out gets rid of the error. Why?
15 | | });
| | ^ - temporary value is freed at the end of this statement
| |_____|
| creates a temporary which is freed while still in use
16 | dog.bark(); // Commenting this out gets rid of the error. Why?
| --- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
error: aborting due to previous error
For more information about this error, try `rustc --explain E0716`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
这是有道理的,因为我传递给dog.set_formatter(...) 的闭包确实是一个临时的(我猜)当执行继续到dog.bark(); 时被释放。
我知道在set_formatter 的实现中去掉显式生命周期注释似乎可以满足编译器的要求(注意dyn 之前缺少的'a):
pub fn set_formatter(&mut self, _fmt: & dyn Fn() -> ()) -> () {}
但是,我不明白以下内容:
- 为什么当我在闭包中注释掉
println!("{}", x);时问题消失了?我仍然传递了一个我希望编译器抱怨的临时变量,但事实并非如此。 - 为什么我在最后注释掉
dog.bark();后问题就消失了?同样,我仍在传递一个已释放的临时闭包,但现在编译器很高兴。为什么?
【问题讨论】:
标签: rust closures lifetime borrow-checker trait-objects