summaryrefslogtreecommitdiff
path: root/source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md
diff options
context:
space:
mode:
Diffstat (limited to 'source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md')
-rw-r--r--source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md62
1 files changed, 62 insertions, 0 deletions
diff --git a/source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md b/source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md
new file mode 100644
index 00000000..71ffb83f
--- /dev/null
+++ b/source/_posts/Rust-闭包-lifetime-may-not-live-long-enough-问题.md
@@ -0,0 +1,62 @@
+---
+title: Rust 闭包 lifetime may not live long enough 问题
+date: 2023-05-24 18:04:23
+tags: [Technique]
+---
+
+代码:
+```rust
+...
+ fn handlers(self) -> crate::server::request::Handlers {
+ vec![(
+ "/tree",
+ routing::get(move || async {
+ (
+ StatusCode::OK,
+ Json(json!(self.clone().tree(self.clone().root))),
+ )
+ }),
+ )]
+ }
+...
+```
+
+编译错误:
+```text
+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` 在闭包执行完毕后仍然有效。
+
+解决这个问题的思路是:确保闭包中的所有引用都在闭包执行完毕之前就不再被使用。
+就是说,要将闭包的作用域限制在一个更短的生命周期内,或者使用其他方式来避免闭包捕获长期存在的引用:
+
+```rust
+
+...
+ 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)) }),
+ )]
+ }
+...
+``` \ No newline at end of file