I have some code like the following that used to compile fine until yesterday (nightly-2018-01-03), but now fails with the latest nightly. Is this a regression with how NLL interacts with RefCell, or was the code never meant to be valid?
Compiling playground v0.0.1 (file:///playground)
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> src/main.rs:12:16
|
12 | foo.v.push(foo.b);
| --- ^^^ immutable borrow occurs here
| |
| mutable borrow occurs here
error: aborting due to previous error
error: Could not compile `playground`.
To learn more, run the command again with --verbose.
no clue as to what's happening (sorry!), but it will be easier to help you if you include the error(s) the compiler gives (when it comes to lifetime issues, even the "pros" need help )
i find your structure a bit odd. Why not have the function inside the struct (under impl)? since you are anyway accessing the struct, i think it is better to have the function inside.
That was just for the example. In the actual code it's a method and the problem is the same. I'm more interested into why it suddenly stopped compiling.
This sounds like a long existing issue with borrows in RefCell and the likes. Not a 100% sure, but I've experienced something similar here. As a correction this works:
#![feature(nll)]
use std::cell::RefCell;
struct Foo {
pub v: Vec<u32>,
pub b: u32,
}
fn f(foo: RefCell<Foo>) {
let mut foo = foo.borrow_mut();
let b = foo.b;
foo.v.push(b);
}
fn main() {
let foo: RefCell<Foo> = RefCell::new(Foo {v: Vec::new(), b: 0});
f(foo);
}
PS: I think essentially the compiler first borrows mutably foo for the push and hence does not allow to reference any of its internals until the borrow is done. Similar to the issue I've pointed out these are compiler issues and depend on how the AST is parsed and borrows evaluated.