Borrow checker and struct elements


#1

I’m trying to develop a simple directory walker. Short version: I have a directory node stack, each node contains a VecDeque of directory elements to process. I want to keep looping while there are directory nodes to process, and in that loop keep looping while there are directory entries to process.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=856c7f044261dbe768472ff84e1bb380

This will not build because pop_front() needs a mutable variable, but it can’t borrow one because there’s already a reference to the struct. I understand what the problem is, and I understand that I need to restructure the code – but whatever solutions I come up with keep having the same problem. I fear that my brain is stuck in a way of thinking which isn’t compatible with the borrow/mutability checker. So I’m looking for some inspiration.


#2

AFAICT you don’t actually have any conflict – you just need a mutable reference.

error[E0596]: cannot borrow `dn.eq` as mutable, as it is behind a `&` reference
  --> src/lib.rs:46:27
   |
45 |   while let Some(dn) = stack.last() {
   |                  -- help: consider changing this to be a mutable reference: `&mut ProcDirNode`
46 |     while let Some(_de) = dn.eq.pop_front() {
   |                           ^^^^^ `dn` is a `&` reference, so the data it refers to cannot be borrowed as mutable

If you change to stack.last_mut(), then dn will be a &mut reference which you can pop from.


#3

Well that was easy! Thanks!


#4

That said, your stack loop will never terminate (unless it’s empty to begin with), so there’s probably more to your story. If you need to modify the stack from within that loop, you’ll have to try something else, like popping instead of referencing its last item.


#5

Yeah, you’re right – there’s more to it, but I wanted to minimize the code to eliminate all other errors/warnings.


#6

I just realized that 1.31’s nonlexical-lifetimes will let you modify that stack in the loop, as long as you do it after the last use of the borrowed dn. This used to be more painful!