如何指示 rust 将值移动到另一个范围?

How to indicate to rust to move a value to another scope?

提问人:matanmarkind 提问时间:9/7/2023 更新时间:9/7/2023 访问量:61

问:

以下代码无法编译,因为编译器思维仍保留在 的作用域中,而不是移动到 的作用域中。为什么编译器不明白不需要绑定到外部作用域,可以移动到 的作用域?smainspawnsspawn

struct MyStruct {}

impl MyStruct {
    async fn run(&self) {
        println!("Hello");
    }
}

#[tokio::main]
async fn main() {
    let s = MyStruct{};
    tokio::task::spawn(s.run());
}

main()

错误:

[E0597] Error: `s` does not live long enough
    ╭─[command_21:1:1]
    │
 11 │     let s = S{};
    ·         ┬  
    ·         ╰── binding `s` declared here
 12 │     tokio::task::spawn(s.run());
    ·                        ───┬───  
    ·                           ╰───── borrowed value does not live long enough
    ·                           │     
    ·                           ╰───── argument requires that `s` is borrowed for `'static`
 13 │ }
    · ┬  
    · ╰── `s` dropped here while still borrowed
────╯

我找到了几个解决方法,但很高兴听到是否有更好的方法:

如果我将 fn 签名更改为移动自己而不是借用:

run(self)  // removed the &.

或者,如果我无法更改签名,则可以在呼叫站点添加明确的移动:

tokio::task::spawn(async move { s.run().await });

有没有更好的方法?

所有权

评论

0赞 Chayim Friedman 9/7/2023
你已经找到的方法就是方法。我不确定我是否理解你的问题:编译器不会这样做,因为这些是语言的规则。
3赞 Ivan C 9/7/2023
在您的示例中,is not borrowed by ,它被 借用,而 又将 borrow 传递给匿名者,然后将其移动到 .正是这最后一步导致了编译器错误。sspawnrunimpl Futurespawn

答:

2赞 Colonel Thirty Two 9/7/2023 #1

正如你所提到的,显式块是最好的方法。async move

返回 borrow 但需要 future(即不 borrow 的未命名类型)。你不能只是“将自己移入未来”,因为这需要返回不同的类型。但是,您可以通过 创建一个新的未来,它包含 ,并且只调用 。Futurerunselftokio::task::spawn'staticrunasync moveselfrun