代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
...
fn handlers(self) -> crate::server::request::Handlers {
vec![(
"/tree",
routing::get(move || async {
(
StatusCode::OK,
Json(json!(self.clone().tree(self.clone().root))),
)
}),
)]
}
...

编译错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
error: lifetime may not live long enough
--> src/storage/filesystem/mod.rs:45:34
|
45 | routing::get(move || async {
| __________________________-------_^
| | | |
| | | return type of closure `{async block@src/storage/filesystem/mod.rs:45:34: 50:14}` contains a lifetime `'2`
| | lifetime `'1` represents this closure's body
46 | | (
47 | | StatusCode::OK,
48 | | Json(json!(self.clone().tree(self.clone().root))),
49 | | )
50 | | }),
| |_____________^ returning this value requires that `'1` must outlive `'2`
|
= note: closure implements `Fn`, so references to captured variables can't escape the closure

这是因为 handlers 里面的闭包捕获了一个引用,并且尝试返回一个包含该引用的值导致的。

细说就是:闭包内部使用了 self.clone() 来获取一个新的实例,然后在异步块中返回一个 JSON 对象,这个 JSON 对象依赖于 self.tree() 的结果。因为闭包捕获了 self 的引用,所以它必须保证 self 在闭包执行完毕后仍然有效。

解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。
就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:

1
2
3
4
5
6
7
8
9
10

...
fn handlers(self) -> crate::server::request::Handlers {
let tree = json!(self.clone().tree(self.clone().root));
vec![(
"/tree",
routing::get(move || async { (StatusCode::OK, Json(tree)) }),
)]
}
...