我有一个铁 rust 发生器,它的参考值是&self,但我得到的错误是let mut g = t.inner()行上的borrow may still be in use when generator yields,具体地说是参考值t.

据我所知,编译器不能保证t比生成器更长,尽管我已经添加了生命周期.有没有一种适当的方法来做到这一点,或者这只是一个生成器的警告?

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=25a8034c25c248457c348729d9f363a6

#![feature(generators, generator_trait)]

use std::{ops::Generator, pin::Pin};

struct T(i32);

impl T {
    // The nested generator and `&self` are important.
    // Changing it to `self` and removing the lifetime fixes the error.
    // Could elide the lifetime, but it's there for clarity.
    
    fn inner<'a>(&'a self) -> impl Generator<(), Yield = i32, Return = ()> + Unpin + 'a {
        move || {
            // In the real example, the receiver type is `&mut self` so we need
            // to pretend we have a reference to self in the generator.
            // The real example is too large to include here.
            let _ = self.0;
            
            yield 0;
        }
    }
}

fn main() {
    let t = T(10);
    
    // Uncommenting this ref lets it compile for some reason?
    // let t = &t;
    
    let mut g = move || {
        
        // On the other hand, this doesn't do anything other than moving the error
        // let t = &t;
    
        // The error is on the implicit reference to `t`
        // More clear if it's changed to `let mut g = (&t).inner();`
        let mut g = t.inner();

        // Pretend to do something with the generator's results.
        let _ = Pin::new(&mut g).resume(());
        yield 0;
    };
    
    let _ = Pin::new(&mut g).resume(());
}

推荐答案

这是因为生成器被编译为状态机,当生成器为yield时,状态机会更改其状态.在您的示例中,由于您在g内使用move t,因此与t.inner()一起使用的(隐式)borrow &t需要borrow 生成器.但是,当您放弃时,您还需要可变地borrow 生成器,这是不允许的.

这可以通过不让生成器获得t的所有权来解决,这需要不变地borrow 生成器来获得&t,而是获得&t的所有权,这就是当你let t = &t的时候发生的事情.

您也可以通过从g的定义中删除move来获得相同的行为:

let mut g = || {
    // The error is on the implicit reference to `t`
    // More clear if it's changed to `let mut g = (&t).inner();`
    let mut g = t.inner();
    // Pretend to do something with the generator's results.
    let _ = Pin::new(&mut g).resume(());
    yield 0;
};

Rust相关问答推荐

将数组转换为HashMap的更简单方法

Rust函数的返回值不能引用局部变量或临时变量

在macro_rule中拆分模块和函数名

如何在嵌套的泛型 struct 中调用泛型方法?

为什么Option类型try块需要类型注释?

是否提供Bundle 在可执行文件中的warp中的静态文件?

随机函数不返回随机值

Rust Option 的空显式泛型参数

Rust 中多个 & 符号的内存表示

如何从borrow 的异步代码运行阻塞代码?

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

在Rust中实现Trie数据 struct 的更好方式

如何使用 Rust Governor 为每 10 秒 10 个请求创建一个 RateLimiter?

为什么不能在 Rust 中声明静态或常量 std::path::Path 对象?

borrow 匹配手臂内部的可变

如何刷新 TcpStream

在 Rust 中,将可变引用传递给函数的机制是什么?

将 `&T` 转换为新类型 `&N`

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

如何在 Rust 中构建一个 str