简体   繁体   English

Rust:无限循环借用检查器

[英]Rust: borrow checker in infinite loop

I'm currently building an application with a main loop. 我目前正在构建一个带有主循环的应用程序。 Settings are added to the struct as references to avoid boxing. 设置将添加到结构中,以作为避免装箱的参考。 The problem is, even though it seems perfectly valid, the borrow checker does not validate infinite loops. 问题是,即使看起来完全正确,借用检查器也无法验证无限循环。 As an example, this does not compile: 例如,它不会编译:

struct Demo<'a> {
    data: Vec<&'a u8>,
}

impl<'a> Demo<'a> {
    fn new(data: Vec<&'a u8>) -> Self {
        Demo { data }
    }

    fn bug(mut self) -> ! {
        let a = 8;
        {
            self.data.push(&a);
            {
                self.forever();
            }
        }
    }

    fn forever(self) -> ! {
        loop {
            for dat in &self.data {
                println!("{}", dat);
            }
        }
    }
}

fn main() {
    let v = vec![&1, &1, &2, &3];
    Demo::new(v).bug();
}

My question is: how could I refactor the code above to avoid boxing the data, but still being able to use a main loop. 我的问题是:如何重构上面的代码以避免将数据装箱,但仍然能够使用主循环。

Within an impl<'a> Demo<'a> , all the self s have the exact same type, for the exact same 'a . impl<'a> Demo<'a> ,所有self具有完全相同的类型,对于完全相同的'a But in your case, you are trying to shorten the lifetime. 但是在您的情况下,您正在尝试缩短使用寿命。 You can do this by rebinding self : 您可以通过重新绑定self来做到这一点:

let mut this = self;
// the compiler infers that `this` must have a shorter lifetime:
this.data.push(&a);
this.forever();

( link to the playground ) 链接到游乐场

Your other example can be fixed in a similar way . 您的其他示例可以用类似的方式修复。

The problem here is not so much that the borrow checker can't see the infinite loop but that you are actively lying to the compiler. 这里的问题不仅仅在于借用检查器看不到无限循环,而是您正在积极地向编译器撒谎。 When constructing the Demo<'a> in main() , the lifetime 'a is a distinct lifetime (bound to the scope of main() ). 当在main()构造Demo<'a>时,生存期'a是一个不同的生存期(绑定到main()的范围内)。 Within bug() you now push a new reference which has to last as long as the lifetime 'a has already been established to be . 现在,您可以在bug()推送一个新引用,该引用必须一直持续到生存期'a已经被确定为 There is no way out of this. 这是没有办法的。

You can, however, create references which are guaranteed to live at least as long as any lifetime: 但是,您可以创建引用,保证其寿命至少与任何生存期一样长:

fn bug(mut self) -> ! {
    let a: &'static u8 = &8;
    {
        self.data.push(a);
        {
            self.forever();
        }
    }
}

This will work, because no matter what 'a is, 'static will live at least as long. 这将起作用,因为无论'a是什么, 'static寿命至少会持续很长时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM