I have a struct UI holding a mutable reference to Stdout. Instead of mutating it on update, I'd prefer to replace it with an entirely new UI:
use std::io::{stdout, Result, Stdout, Write};
struct UI<'s> {
stdout: &'s mut Stdout,
v: Box<()>, // If remove this field, the error goes away.
}
impl<'s> UI<'s> {
fn new(stdout: &'s mut Stdout) -> Result<Self> {
let ui = UI {
stdout: stdout,
v: Box::new(()),
};
Ok(ui)
}
fn write(&mut self) -> Result<()> {
write!(self.stdout, "heyyyyy")?;
self.stdout.flush()?;
Ok(())
}
}
fn main() -> Result<()> {
let mut stdout = stdout();
let mut ui = UI::new(&mut stdout)?;
ui = UI::new(&mut stdout)?;
ui.write()?; // If you comment this line out, the error goes away.
Ok(())
}
playground
The borrow checker complains that stdout is borrowed mutably twice:
error[E0499]: cannot borrow `stdout` as mutable more than once at a time
--> src/main.rs:30:18
|
28 | let mut ui = UI::new(&mut stdout)?;
| ----------- first mutable borrow occurs here
29 |
30 | ui = UI::new(&mut stdout)?;
| -- ^^^^^^^^^^^ second mutable borrow occurs here
| |
| first borrow might be used here, when `ui` is dropped and runs the destructor for type `UI<'_>`
There are two weird behaviors:
If I remove field v, the error goes away.
If I remove ui.display()?, the error also goes away.
What's the problem here?
Addressing #kmdreko's suggestion:
The first point is explained in the error message, albeit in a roundabout way if you don't know what's going on. Box implements Drop, so that it can deallocate its contents when destroyed; and therefore UI automatically implements Drop, which means there is code executed which could access stdout between reborrowing it for a new UI and assigning it to ui.
Then why does this return an error?
fn main() -> Result<()> {
let mut stdout = stdout();
let mut ui = UI::new(&mut stdout)?;
for _ in 0..10 {
drop(ui);
ui = UI::new(&mut stdout)?;
ui.write()?;
}
Ok(())
}
error[E0499]: cannot borrow `stdout` as mutable more than once at a time
--> src/main.rs:33:22
|
28 | let mut ui = UI::new(&mut stdout)?;
| ----------- first mutable borrow occurs here
...
33 | ui = UI::new(&mut stdout)?;
| -- ^^^^^^^^^^^ second mutable borrow occurs here
| |
| first borrow might be used here, when `ui` is dropped and runs the destructor for type `UI<'_>`
Someone on Reddit suggested to implement take(self) -> &'s mut Stdout for UI and it works, but I have no idea why. Playground.
When replacing a value, the new value must be created first:
struct Noisy(u8);
impl Noisy {
fn new(v: u8) -> Self {
eprintln!("creating {}", v);
Self(v)
}
}
impl Drop for Noisy {
fn drop(&mut self) {
eprintln!("dropping {}", self.0);
}
}
fn main() {
let mut ui = Noisy::new(1);
ui = Noisy::new(2);
}
creating 1
creating 2
dropping 1
dropping 2
This means that your two UI structs would attempt to coexist. Since they both have a mutable reference to stdout, the Drop::drop implementation might mutate stdout, which would violate the rules of references as there would be multiple active mutable references at one point.
When you don't call write, the non-lexical borrow checker sees that the borrow isn't needed, so there's no problem.
Then why does [explicitly dropping the value before reassigning it] return an error?
Because that is a limitation of the current borrow checker implementation.
See also:
What are non-lexical lifetimes?
Why does linking lifetimes matter only with mutable references?
Does Rust free up the memory of overwritten variables?
Moved variable still borrowing after calling `drop`?
What are the options to end a mutable borrow in Rust?
Related
I have a function which takes a Vec and pushes zero or more elements to it. The Vec and the reference passed to the function are both mut. When I try to get the length of the Vec upon return (to see how many elements were pushed), I get the dreaded "cannot borrow 'foo' as immutable because it is also borrowed as mutable" error.
In general, I get why this error exists in general. I don't get why it's necessary here.
Surely there's a way to do this -- I can't be the first person who has tried something like this.
Here's a stripped-down version of what I'm trying to do, that replicates the error.
fn main() {
let mut stack = vec!["one"];
push(&mut stack, "two");
}
fn push<'a>(stack: &'a mut Vec<&'a str>, value: &'a str) {
stack.push(value);
}
#[test]
fn test_len() {
let mut stack = vec!["one"];
push(&mut stack, "two");
assert_eq!(stack.len(), 2);
}
error[E0502]: cannot borrow `stack` as immutable because it is also borrowed as mutable
--> src/main.rs:14:16
|
13 | push(&mut stack, "two");
| ---------- mutable borrow occurs here
14 | assert_eq!(stack.len(), 2);
| ^^^^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
Don't force the references lifetime and the lifetime of the mutable borrow to be the same.
fn push<'a>(stack: &mut Vec<&'a str>, value: &'a str) {
stack.push(value);
}
playground link
I'm having trouble trouble understanding why this code can't compile:
struct Ctx<'a> {
n: u64,
phantom: std::marker::PhantomData<&'a u8>,
}
fn process<'a, 'b: 'a>(ctx: &'b mut Ctx<'a>) {
ctx.n += 1;
}
fn main() {
let mut ctx = Ctx { n: 0, phantom: std::marker::PhantomData };
let ref_ctx = &mut ctx;
process(ref_ctx);
process(ref_ctx);
}
The code is silly, but the error is the same as on the "real" code:
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `*ref_ctx` as mutable more than once at a time
--> src/main.rs:14:13
|
13 | process(ref_ctx);
| ------- first mutable borrow occurs here
14 | process(ref_ctx);
| ^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to previous error
If change the process signature to
fn process(ctx: &mut Ctx<'a>) {
Then it compiles, but I need the lifetimes annotations because in practice Ctx contains references that needs to be annotated. I feel like the problem is 'b: 'a because is could be telling that the borrow MUST outlive the references in Ctx, but it feels weird that just calling a function that returns nothing would extend the borrow,
That feels like a beginner's question, but it definitely has me stumped.
edit:
The code above is minimal because I wanted to avoid explaining the whole context (pun intended), but it might be necessary to find a practical solution. Sorry, that's going to be a bit long.
The real Ctx is here, it's struct that wraps a few Varnish C pointers and gets passed to plugins so they can read it and possibly change it, notably manipulating HTTP objects.
An important part of Ctx is the WS contained in it. It's a workspace that can return non-overlapping slices of writable data that will be deleted automatically once a task has been completed. For the compiler, the best we can tell it is "any slice allocated in the WS will survive for as long as the Ctx wil live".
WS can be used in two ways:
either directly by a plugin to request a slice it'll fill in
or by the boilerplate that's currently python-generated to convert Varnish types into C types. Typically, the plugin returns a String and the boilerplate will allocate a WS slice and copy the data for storage. And example of generated code looks like this:
// the C-matching function that needs to exist for the plugin frame work to pick it up
unsafe extern "C" fn vmod_c_unset_hdr(vrt_ctx: * mut varnish_sys::vrt_ctx, arg1: varnish_sys::VCL_STRING) {
// create the rust Ctx from the pointer
let mut _ctx = Ctx::new(vrt_ctx);
// call the plugin function
match vmod::unset_hdr(
&mut _ctx,
&*arg1.into_rust()
).into_result() { // make sure we have a Result by wrapping lone values
Err(ref e) => { _ctx.fail(e); }, // yell if we didn't got and Err
Ok(v) => v.into_vcl(&mut _ctx.ws), // convert the Ok value into a C type, possibly by copying it into the workspace
}
}
Now, so far, the code at the commit I shared works (hurray), but I get into trouble when I try to implement WS_ReserveAll and WS_Release: basically, grab all the free space you can, write what you need, and then tell Varnish how much you used so the rest is reclaimed and can be used by future calls.
Of course, you can only WS_ReserveAll() once before you need to WS_Release so that felt like a perfect job for Rust.
I though I'd create a new type ReservedBuf, by adding this to the code:
impl<'a> struct WS<'a> {
// some lines omitted
pub fn reserve(&'a mut self) -> ReservedBuf<'a> {
let wsp = unsafe { self.raw.as_mut().unwrap() };
assert_eq!(wsp.magic, varnish_sys::WS_MAGIC);
unsafe {
let sz = varnish_sys::WS_ReserveAll(wsp) as usize;
let buf = from_raw_parts_mut(wsp.f as *mut u8, sz as usize);
ReservedBuf {
buf,
wsp: self.raw,
b: wsp.f as *const u8,
len: 0,
}
}
}
}
pub struct ReservedBuf<'a> {
pub buf: &'a mut [u8],
wsp: *mut varnish_sys::ws,
b: *const u8,
len: usize,
}
impl<'a> ReservedBuf<'a> {
pub fn seal(mut self, sz: usize) -> &'a [u8] {
unsafe {
self.len = std::cmp::min(sz, self.buf.as_ptr().add(sz).offset_from(self.b) as usize);
from_raw_parts_mut(self.buf.as_mut_ptr(), self.len)
}
}
}
impl<'a> Drop for ReservedBuf<'a> {
fn drop(&mut self) {
unsafe {
let wsp = self.wsp.as_mut().unwrap();
assert_eq!(wsp.magic, varnish_sys::WS_MAGIC);
varnish_sys::WS_Release(wsp, self.len as u32);
}
}
}
And it appears to work well enough in the limited tests I ran. My plugin function can be this for example:
pub fn ws_reserve<'a, 'b: 'a>(ctx: &'b mut Ctx<'a>, s: &str) -> Result<varnish_sys::VCL_STRING, String> {
let mut rbuf = ctx.ws.reserve();
let s_buf = s.as_bytes();
let vcl_string = rbuf.buf.as_ptr() as *const i8;
rbuf.buf.write(s_buf);
rbuf.buf.write(b" ");
rbuf.buf.write(s_buf);
rbuf.buf.write(b" ");
rbuf.buf.write(s_buf);
rbuf.buf.write(b"\0");
rbuf.seal(0);
Ok(vcl_string)
}
but I need the lifetime annotations, otherwise I get:
--> src/vmod.rs:21:27
|
20 | pub fn ws_reserve(ctx: &mut Ctx, s: &str) -> Result<varnish_sys::VCL_STRING, String> {
| --------
| |
| these two types are declared with different lifetimes...
21 | let mut rbuf = ctx.ws.reserve();
| ^^^^^^^ ...but data from `ctx` flows into `ctx` here
but with the lifetime annotations, the generated-code calling ws_reserve complains:
unsafe extern "C" fn vmod_c_ws_reserve(vrt_ctx: * mut varnish_sys::vrt_ctx, arg1: varnish_sys::VCL_STRING) -> varnish_sys::VCL_STRING {
let mut _ctx = Ctx::new(vrt_ctx);
match vmod::ws_reserve(
&mut _ctx,
&*arg1.into_rust()
).into_result() {
Err(ref e) => { _ctx.fail(e); ptr::null() },
Ok(v) => v.into_vcl(&mut _ctx.ws),
}
}
error[E0499]: cannot borrow `_ctx` as mutable more than once at a time
--> /home/gquintard/project/varnish-rs/vmod_test/target/debug/build/vmod_example-7ff3d57b642f2bfa/out/generated.rs:69:29
|
66 | &mut _ctx,
| --------- first mutable borrow occurs here
...
69 | Err(ref e) => { _ctx.fail(e); ptr::null() },
| ^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
error[E0499]: cannot borrow `_ctx.ws` as mutable more than once at a time
--> /home/gquintard/project/varnish-rs/vmod_test/target/debug/build/vmod_example-7ff3d57b642f2bfa/out/generated.rs:70:33
|
66 | &mut _ctx,
| --------- first mutable borrow occurs here
...
70 | Ok(v) => v.into_vcl(&mut _ctx.ws),
| ^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `vmod_example` due to 2 previous errors
I guess I sort of understand the compiler qualms about the issues, and I might have painted myself into a corner, but I don't see how to solve this.
When we take a closer look at your code we see you write this:
fn process<'a, 'b: 'a>(ctx: &'b mut Ctx<'a>) {
This 'b: 'a reads as 'b outlives 'a. So you're basically writing a method which borrows ctx longer than what ctx is holding internally with 'a.
With that knowledge it seems very logical why this won't work.
let mut ctx = Ctx { n: 0, phantom: std::marker::PhantomData };
let ref_ctx = &mut ctx;
process(ref_ctx); // Borrow ref_ctx for at least the lifetime of `Ctx::<'a>`
process(ref_ctx); // Can't borrow it again since `'a` has not expired yet
What you're trying to do is probably this:
fn process<'a: 'b, 'b>(ctx: &'b mut Ctx<'a>) {
Borrow ctx for the lifetime 'b which is less long than 'a
If that's the case you can just write this:
fn process<'a>(ctx: &mut Ctx<'a>) {
Or even this:
fn process(ctx: &mut Ctx) {
If this isn't what you're trying to do I hope it still makes sense that using the constraint 'b: 'a creates an impossible borrow.
Goal
Create function/macro which has an api like such:
fn writesperse(
buf: &mut String,
items: impl IntoIterator<Item=impl fmt::Display>,
sep: impl fmt::Display,
) -> fmt::Result {
// intersperse impl elided
}
with the main consumer of this api being a struct similar to:
use std::fmt;
// Drives building of query
struct QueryBuilder<'a> {
buf: String,
data: &'a Data,
state: State,
}
impl<'a> QueryBuilder<'a> {
// example method showing how writesperse might be used
fn f(&mut self) -> fmt::Result {
writesperse(
&mut self.buf,
self.data.names().map(|n| self.state.resolve(n)),
", ",
)
}
}
// Represents mutable container for computed values
struct State;
impl State {
fn resolve(&mut self, _name: &str) -> &StateRef {
// mutate state if name has not been seen before (elided)
&StateRef
}
}
// Represents example computed value
struct StateRef;
impl fmt::Display for StateRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "STATEREF")
}
}
// Immutable container with various collections of objects
struct Data;
impl Data {
// example iterator of references to some owned data
fn names(&self) -> impl Iterator<Item=&str> {
::std::iter::once("name")
}
// another iterator of a different references
fn items(&self) -> impl Iterator<Item=&DataRef> {
::std::iter::once(&DataRef)
}
}
// Represents some type Data might own
struct DataRef;
Error
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:13:50
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 13:35...
--> src/lib.rs:13:35
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:13:39
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^
note: but, the lifetime must be valid for the method call at 13:13...
--> src/lib.rs:13:13
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that a type/lifetime parameter is in scope here
--> src/lib.rs:13:13
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What I've tried
My only success thus far has been to manually do the intersperse logic at each site where it is needed.
let mut iter = some_iter.into_iter();
if let Some(i) = iter.next() {
// do any state mutation here so mutable reference is released
let n = self.state.resolve(n);
write!(&mut self.buf, "{}", n)?;
}
for i in iter {
// do same thing above
}
If I try and make State::resolve immutable, (which means I would need to pre-compute the values which is not desirable), I get a different error.
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:13:35
|
11 | writesperse(
| ----------- mutable borrow later used by call
12 | &mut self.buf,
| ------------- mutable borrow occurs here
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^ ---- second borrow occurs due to use of `self` in closure
| |
| immutable borrow occurs here
This error is easier to understand. However, I don't understand why what I am trying to do is disallowed. Why can I not hand out a mutable reference to QueryBuilder's buf and an iterator of references to objects within State and/or Data at the same time?
Ultimately, my number one priority is abstracting the intersperse logic into some function or macro which expects an Iterator<Item=fmt::Display>. It would be an added bonus if this Iterator could possibly mutate state and return a reference to its data. I don't think this is possible though, at least from my understanding of the streaming-iterator crate.
Thanks for your help!
writesperse is not the problem here, resolve is.
Because it takes &mut self and returns a reference with a lifetime bound to self, you can't call resolve a second time unless the reference obtained from the first call has been dropped. You can see this in this simplified f (compiler error interspersed):
// error[E0499]: cannot borrow `self.state` as mutable more than once at a time
fn f(&mut self) {
let a = self.state.resolve("alec");
// ---------- first mutable borrow occurs here
let _b = self.state.resolve("brian");
// ^^^^^^^^^^ second mutable borrow occurs here
println!("{}", a);
// - first borrow later used here
}
Part of the contract of an Iterator is that it does not yield internal references. So |n| self.state.resolve(n) is simply not a closure that can be passed to Iterator::map.
Fixing resolve
If resolve took &self instead of &mut self, this would work because the closure would not need to borrow self.state exclusively; it could return references with the lifetime of the original without worrying about overlap. So let's try that:
fn resolve(&self, _name: &str) -> &StateRef {
// some kind of interior mutability thing here, probably have to return
// `std::cell:Ref<StateRef>` or `MutexGuard<StateRef>` instead, but that
// doesn't matter for this demonstration
&StateRef
}
Oh dear.
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:23:35
|
21 | writesperse(
| ----------- mutable borrow later used by call
22 | &mut self.buf,
| ------------- mutable borrow occurs here
23 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^ ---- second borrow occurs due to use of `self` in closure
| |
| immutable borrow occurs here
What's going on? Because the closure uses self in a context where an immutable reference is required, the closure borrows self, and the &mut self.buf also borrows (part of) self mutably, and they both have to exist at the same time to pass into writesperse. So this looks like a dead end, but it's actually really close: it just needs a small change to f to compile.
fn f(&mut self) -> fmt::Result {
let state = &self.state;
writesperse(
&mut self.buf,
self.data.names().map(|n| state.resolve(n)),
", ",
)
}
The compiler can reason about mutually exclusive partial borrows as long as they happen all within the body of a single function. The compiler will let you borrow self.state and mutably borrow self.buf at the same time as long as the borrows happen in the same function. Creating a variable to borrow self.state makes it so that only state is captured by the closure, not self.
Other options
The above works, if you're able to make resolve take &self. Here are some other ideas:
You could attack the problem from the other direction: make resolve return StateRef by value so it doesn't extend the &mut borrow.
You can achieve the same thing by altering the closure so that it doesn't return a reference; |n| state.resolve(n).to_string() works with no further changes (but it does do a bunch of unnecessary allocation and copying).
You could use Arc or Rc instead of & references and defer all lifetime management to runtime.
You could write a macro that does the repetitive part for you so that writesperse is not necessary.
See also
How do I return a reference to something inside a RefCell without breaking encapsulation? if you need to use interior mutability to make resolve take &self
Mutable borrow of self doesn't change to immutable explains why state is still considered "mutably borrowed" after resolve returns
I'm writing a bot for halite.io, and am having issues understanding some of the effects of borrowing. Here is the code that will not compile:
let scanLoc = hlt::types::Location {
x: oflow(coord.0 + l.x as i32, game_map.width),
y: oflow(coord.1 + l.y as i32, game_map.width),
};
let scan = game_map.get_site(scanLoc, types::STILL);
if (&scan.owner != id) | (scan.owner != 0u8) {
let ang = game_map.get_angle(l, scanLoc);
debug!("angle b/w: {}", ang);
return (l, 2);
}
This is the compiler error:
error[E0502]: cannot borrow `*game_map` as immutable because it is also borrowed as mutable
--> src/MyBot.rs:112:27
|
110 | let scan = game_map.get_site(scanLoc, types::STILL);
| -------- mutable borrow occurs here
111 | if (&scan.owner != id) | (scan.owner != 0u8) {
112 | let ang = game_map.get_angle(l, scanLoc);
| ^^^^^^^^ immutable borrow occurs here
...
116 | }
| - mutable borrow ends here
This is the code for the GameMap functions and struct:
#[derive(Clone, Debug)]
pub struct GameMap {
pub width: u16, // Number of columns.
pub height: u16, // Number of rows.
pub contents: Vec<Vec<Site>>,
}
impl GameMap {
pub fn in_bounds(&self, l: Location) -> bool {
// ...
}
pub fn get_distance(&self, l1: Location, l2: Location) -> u16 {
// ...
}
pub fn get_angle(&self, l1: Location, l2: Location) -> f64 {
// ...
}
pub fn get_location(&self, l: Location, d: u8) -> Location {
// ...
}
pub fn get_site(&mut self, l: Location, d: u8) -> &mut Site {
// ...
}
}
Why does Rust borrow the function mutably, and even if it is borrowing the function would it not return the borrow (ending the lifetime) when returning the result, so it would be available to borrow afterwards?
Editor's note: This specific problem has been solved by the introduction of non-lexical lifetimes.
Let's look at a tiny reproduction:
struct Site {
owner: u8,
}
struct GameMap {
site: Site,
}
impl GameMap {
fn do_anything(&self) {}
fn get_site(&mut self) -> &mut Site {
&mut self.site
}
}
fn main() {
let mut game_map = GameMap {
site: Site { owner: 0 },
};
let site = game_map.get_site();
game_map.do_anything();
}
error[E0502]: cannot borrow `game_map` as immutable because it is also borrowed as mutable
--> src/main.rs:22:5
|
21 | let site = game_map.get_site();
| -------- mutable borrow occurs here
22 | game_map.do_anything(); // Compiler error!
| ^^^^^^^^ immutable borrow occurs here
23 | }
| - mutable borrow ends here
Our GameMap only owns a single Site, but that's enough. The call to get_site returns a reference (in this case it happens to be mutable):
fn get_site(&mut self) -> &mut Site
Thanks to lifetime elision, this is the same as
fn get_site<'a>(&'a mut self) -> &'a mut Site
This means that the returned reference is allowed to point to something inside of GameMap (which it does). Then we keep that reference in a variable - site!
That means that we can no longer use any immutable references to game_map as they might have been (or will in the future be) invalidated by the changes that can be made to the map through the mutable reference:
At any given time, you can have either one mutable reference or any number of immutable references.
References must always be valid.
— The Rust Programming Language chapter on references and borrowing
Why does Rust borrow the function mutably, and even if it is borrowing the function would it not return the borrow (ending the lifetime) when returning the result, so it would be available to borrow afterwards?
Rust borrows your struct mutably because you are calling a method that requires a mutable reference (&mut self). That method then returns a mutable reference, transferring the borrow of the struct to the returned value. The borrow ends when the returned value goes out of scope.
So, how do you fix it? Probably the most flexible solution is to introduce a scope to constrain the mutable borrow:
let zhu_li_do_the_thing = {
let site = game_map.get_site();
site.owner == 5 || site.owner == 42
};
if zhu_li_do_the_thing {
game_map.do_anything();
}
Another is the same idea, but requires that you never store the borrow in a variable at all. Thus the mutable borrow doesn't last beyond that statement:
if game_map.get_site().owner == 42 {
game_map.do_anything();
}
It's common for idiomatic Rust code to have foo and foo_mut variants of a method, for when you don't need mutability. This may not help if you need to mutate game_map while the immutable borrow of site is still outstanding.
fn get_site(&self) -> &Site {
&self.site
}
fn get_site_mut(&mut self) -> &mut Site {
&mut self.site
}
let site = game_map.get_site();
if site.owner == 5 || site.owner == 42 {
game_map.do_anything();
}
See also:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
What are non-lexical lifetimes?
I am implementing an in-place recursive parser in rust and I am getting some borrow errors. The code snippet reproduces the problem although it is not very useful
use std::vec::Vec;
struct MyBorrows<'a> {
val : &'a mut i32
}
impl <'a> MyBorrows<'a> {
fn new(v : &'a mut i32) -> MyBorrows<'a> {
MyBorrows { val : v }
}
}
fn main() {
let mut my_val = 23;
let mut my_vec : Vec<Box<MyBorrows>> = Vec::new();
my_vec.push(Box::new(MyBorrows::new(&mut my_val)));
for i in [1..4].iter() {
let mut last : &mut Box<MyBorrows> = my_vec.last_mut().unwrap();
let mut new_borrow = Box::new(MyBorrows::new(last.val));
my_vec.push(new_borrow);
}
}
This gives me the following error:
error[E0499]: cannot borrow `my_vec` as mutable more than once at a time
--> test.rs:20:9
|
18 | let mut last : &mut Box = my_vec.last_mut().unwrap();
| ------ first mutable borrow occurs here
19 | let mut new_borrow = Box::new(MyBorrows::new(last.val));
20 | my_vec.push(new_borrow);
| ^^^^^^ second mutable borrow occurs here
21 | }
22 | }
| - first borrow ends here
error: aborting due to 3 previous errors
In my real case, the vector is used as a stack to reference deeper and deeper components of the struct I am parsing into. This is common pattern I use for general purpose parsing in C++ which I am trying to replicate in Rust but I am having problems. Any help will be appreciated.
What you are trying to do is unsound. It looks like you are attempting to create multiple MyBorrows which all mutably borrow the same value, and have them all alive at once (in the vector). Such setups are exactly what Rust is designed to prevent, as that's how data races occur.
What you might instead want to do is immutably borrow the value a bunch, which is legal. So after cleaning up the unnecessary mutable borrows, I've reduced the problem to:
struct MyBorrows<'a> {
val : &'a i32
}
impl <'a> MyBorrows<'a> {
fn new(v : &'a i32) -> MyBorrows<'a> {
MyBorrows { val : v }
}
}
fn main() {
let my_val = 23;
let mut my_vec = vec![];
my_vec.push(Box::new(MyBorrows::new(&my_val)));
for _ in 1..4 {
let last = my_vec.last().unwrap();
let new_borrow = Box::new(MyBorrows::new(last.val));
my_vec.push(new_borrow);
}
}
You get a slightly different error now:
error[E0502]: cannot borrow `my_vec` as mutable because it is also borrowed as immutable
--> test.rs:18:9
|
16 | let last = my_vec.last().unwrap();
| ------ immutable borrow occurs here
17 | let new_borrow = Box::new(MyBorrows::new(last.val));
18 | my_vec.push(new_borrow);
| ^^^^^^ mutable borrow occurs here
19 | }
| - immutable borrow ends here
error: aborting due to previous error
This one is trickier, and you have to realize what is going on when you call my_vec.last() -- it's returning a reference to existing memory in the Vec, precluding anything else from touching the Vec. Currently in Rust, this reference lives until the end of the current block. To get around this, encase the mutable borrow in its own block scope:
fn main() {
let my_val = 23;
let mut my_vec = vec![];
my_vec.push(Box::new(MyBorrows::new(&my_val)));
for _ in 1..4 {
let new_borrow;
{
let last = my_vec.last().unwrap();
new_borrow = Box::new(MyBorrows::new(last.val));
}
my_vec.push(new_borrow);
}
}
Now the mutable borrow ends before the push occurs, and the lifetimes work. Hopefully in the future, we will get non-lexical lifetimes added to the language, so the compiler can figure out that my first example is actually safe.