Search code examples
rustinfinite-loopborrow-checker

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.


Solution

  • Within an impl<'a> Demo<'a>, all the selfs have the exact same type, for the exact same 'a. But in your case, you are trying to shorten the lifetime. You can do this by rebinding 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.