我想我对临时对象、它们的生存期和对它们的引用有一些了解。但是我不明白下面这种情况是怎么回事:
use std::io;
use tokio::signal::unix::{self, SignalKind};
#[tokio::main]
async fn main() -> io::Result<()> {
tokio::select! {
_ = unix::signal(SignalKind::interrupt())?.recv() => (),
_ = unix::signal(SignalKind::terminate())?.recv() => (),
}
Ok(())
}
编译器告诉我们,在第10行select!
宏的末尾释放临时变量。临时变量只能由select!
宏中的receive方法借用。在select!
宏之后,我们立即从函数返回。没有更多的借款了。这种情况下出了什么问题?这个信息"借用"了什么,后来被"闭包"捕捉到了?的意思吗?
error[E0716]: temporary value dropped while borrowed
--> routing_server/src/main.rs:9:13
|
7 | / tokio::select! {
8 | | _ = unix::signal(SignalKind::interrupt())?.recv() => (),
9 | | _ = unix::signal(SignalKind::terminate())?.recv() => (),
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
10 | | }
| | -
| | |
| |_____temporary value is freed at the end of this statement
| borrow later captured here by closure
|
= note: consider using a `let` binding to create a longer lived value
我可以通过为临时变量引入局部变量来解决这个问题。问题更多的是问题出在哪里,而不是如何解决问题。我想我还没有完全理解Rust的概念。
您可以查看使用cargo expand
生成的代码。在这里,您可以看到宏的手臂是在future
中捕获的。
我添加了一个最小的例子,在代码中显示类似的情况,没有使用宏。在这个例子中,await
在future
上被调用,但是编译器的错误信息是一样的。
Signal
不能被删除,因为future
仍然有一个引用指向它。
use std::error::Error;
struct Signal {}
impl Signal {
async fn recv(&mut self) -> () {
()
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// tokio::select! {
// _ = Signal {}.recv() => (),
// }
let future = Signal {}.recv();
future.await;
Ok(())
}
编译错误
16 | let future = Signal {}.recv();
| ^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
17 | future.await;
| ------ borrow later used here