Borrow checker bug - how to proceed?

Is this a borrow checker bug? If so, is it known? If not, what is the procedure for reporting it?

Is this a borrow checker bug?

This is not a bug. Vec opts in to the unstable may_dangle mechanism. This gives the extra ability for a Vec to be dropped even when it contains invalid references, because it promises not to actually access those references. You could do the same, but only using unstable Rust.

This is mostly just a convenience. Your code will compile if you make the ArrayVec dropped earlier, when the references have not yet been invalidated, using drop(bfds); or a scope:

fn this_does_not_compile(&mut self) {
    {
        let mut bfds = ArrayVec::<_, 42>::new();
        bfds.extend(self.fds.iter().take(42).map(OwnedFd::as_fd));
        do_something_with_bfds(&bfds);
    } // bfds will be dropped here
    do_something_with_fds(&mut self.fds);
}

If not, what is the procedure for reporting it?

You'd go to https://github.com/rust-lang/rust/issues/new/choose and file a bug report with the code you have, and a little more explanation of why you think it is a bug and what should happen instead.

3 Likes

Thanks for the explanation! I noticed that adding the extra block allowed the ArrayVec case to compile.

I keep thinking that the Rust compiler places drops at the earliest point where they can legally occur (after the last use of the dropee), instead of placing them at the end of the surrounding explicit scope. I think this is because I'm confusing drop checking with borrow checking - because borrows are "returned" at the earliest point where it is legal to do so. When I think about it, of course Rust is trying to preserve drop order, which may have other complex interactions with program state, so it can't use the same tricks with drops as with borrows. Maybe those "lifetime desugaring" examples in the doc that add extra explicit scopes to explain lifetimes of borrows are adding to my confusion here.

Everything you said is correct. Also, note that dropping is running code that can have arbitrary effects, so the order of effects is important, whereas lifetimes never have any effects — changing lifetime annotations only affects whether the program compiles, not what it does when run.

4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.