struct C {
p: String,
q: String,
}
impl C {
fn call(&mut self) {}
}
fn main(){
let mut c = C { p: "p".to_string(), q: "q".to_string() };
let r_c = &mut c;
let p = &mut r_c.p;
let q = &mut r_c.q; // ???
r_c.call();
p.push('x');
q.push('y');
}
Fails with (playground)
error[E0499]: cannot borrow `*r_c` as mutable more than once at a time
--> src/main.rs:15:9
|
13 | let p = &mut r_c.p;
| ---------- first mutable borrow occurs here
14 | let q = &mut r_c.q; // ???
15 | r_c.call();
| ^^^^^^^^^^ second mutable borrow occurs here
16 | p.push('x');
| ----------- first borrow later used here
I know how to fix error[E0499]. I just don't understand that
mutable borrow occurs in let p = &mut r_c.p;, but why does mutable borrow not occur in let q = &mut r_c.q;?
let p = &mut r_c.p; // --------------------------+borrow `*r_c` first
let q = &mut r_c.q; // ----+borrow `*r_c` second |
// | |
p.push('x'); // ----|---------------------+
q.push('y'); // ----+
if mutable borrow occurs in let q = &mut r_c.q;, the code above should be error. But in fact, the code above compiles.
The first borrow p is enough to be in conflict with the usage of r_c.
No need to repeat the same diagnostic with q.
If you swap these two lines, you have the same message about q.
If you reorder this way
let r_c = &mut c;
r_c.call();
let p = &mut r_c.p;
let q = &mut r_c.q; // ???
p.push('x');
q.push('y');
these conflicts disappear since r_c is not used anymore after .call().
These exclusive references don't really hurt as long as you don't use them; i.e. pass them to functions.
I guess you introduced these references for an experimentation purpose (good thing), but in practice we should try to avoid letting them span over long portions of code (between their creation and their last usage) because conflicts with other operations may occur in the middle.
From the edited question:
but why does mutable borrow not occur in let q = &mut r_c.q;?
It does occur.
The error is on r_c.call() and the message shows the first reference (p) causing this error; the message is first mutable borrow occurs here.
Even if the second reference (q) did not exist, the error would be the same.
If twelve references were taken here, the error would still be the same; no need to repeat the same help message many times.
Related
Let's say I have this code:
let mut s = "hi".to_string();
let c = || s.push_str(" yo");
c();
It doesn't compile and generates this error:
error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable
--> src\test.rs:120:9
|
119 | let c = || s.push_str(" yo");
| - - calling `c` requires mutable binding due to mutable borrow of `s`
| |
| help: consider changing this to be mutable: `mut c`
120 | c();
| ^ cannot borrow as mutable
For more information about this error, try `rustc --explain E0596`.
error: could not compile `test` due to previous error
Why c(); cannot borrow as mutable? It cannot borrow what as mutable? c? In order to make it work, I have to change it to:
let mut s = "hi".to_string();
let mut c = || s.push_str(" yo");
c();
But here I'm just defining a closure c. I'll not modify it, like c = || x;. Why must define it as let mut c?
But here I'm just defining a closure c. I'll not modify it, like c = || x;. Why must define it as let mut c?
Because a closure is fundamentally a structure, each captured item being a member of that structure.
So your code is roughly equivalent to this:
struct S<'a>(&'a mut String);
impl S<'_> {
fn call(&mut self) {
self.0.push_str("yo");
}
}
fn main() {
let mut s = "hi".to_string();
let c = S(&mut s);
c.call();
}
And that fails to compile with more or less the same error:
error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable
--> src/main.rs:14:5
|
13 | let c = S(&mut s);
| - help: consider changing this to be mutable: `mut c`
14 | c.call();
| ^^^^^^^^ cannot borrow as mutable
Now you might object that that's because I defined fn call(&mut self), but if you don't you get the internal part of the same error:
error[E0596]: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
--> src/main.rs:8:9
|
7 | fn call(&self) {
| ----- help: consider changing this to be a mutable reference: `&mut self`
8 | self.0.push_str("yo");
| ^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
That is you can't modify an &mut through an &. Because if you did you could create multiple &s to the same &mut through which you could modify the pointee, and that would essentially give you multiple &mut.
Which is not allowed by Rust's semantics:
At any given time, you can have either one mutable reference or any number of immutable references.
It may not look like c needs to be mutable because you aren't modifying c itself, but for closure types, the mut keyword is what allows it to mutate any external state. It changes the type of the closure to be a FnMut, which the docs refer to as "a mutably capturing closure".
It's about ownership. mut here does not mean that you will mutate c, but that you require mut-level access to the closure in order to execute it.
c borrows s mutably. This should be fairly obvious, because calling c() modifies s.
Now imagine if c would be usable without mut:
let mut s = "hi".to_string();
let c = || s.push_str(" yo");
let c1 = &c;
let c2 = &c;
c1();
c2();
Here, both c1 and c2 would have mutable access to s simultaneously, which is not possible according to Rusts borrowing rules. This is prevented automatically by the compiler, as it changes the type of the closure to FnMut as soon as you access a variable mutably from within the closure.
Then, you need mut access to the closure to execute it and the case becomes a compiler error:
let mut s = "hi".to_string();
let mut c = || s.push_str(" yo");
let c1 = &mut c;
let c2 = &mut c;
c1();
c2();
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> src/main.rs:5:10
|
4 | let c1 = &mut c;
| ------ first mutable borrow occurs here
5 | let c2 = &mut c;
| ^^^^^^ second mutable borrow occurs here
6 |
7 | c1();
| -- first borrow later used here
This question already has an answer here:
Error while trying to borrow 2 fields from a struct wrapped in RefCell
(1 answer)
Closed 3 years ago.
Trying to get mutable references to separate fields through a MutexGuard:
struct MyObject {
pub a: i32,
pub b: i32,
}
fn func_1(mtx: &Mutex<MyObject>) {
let mut obj = mtx.lock().unwrap();
let a = &mut obj.a;
let b = &mut obj.b;
*a += 1;
*b *= 2;
}
results in an error:
error[E0499]: cannot borrow `obj` as mutable more than once at a time
--> src/main.rs:11:18
|
10 | let a = &mut obj.a;
| --- first mutable borrow occurs here
11 | let b = &mut obj.b;
| ^^^ second mutable borrow occurs here
12 |
13 | *a += 1;
| ------- first borrow later used here
This has me a bit confused. This works when obj is a simple mutable reference (&mut MyObject). I thought maybe the Deref trait was the one causing the problem, but it also works if obj is a &mut Box<MyObject>.
See it on the Rust Playground.
What am I missing?
Mutex::lock returns a RAII lock guard in addition of ways to deal with its contained value. To get its contained value as &mut (and subsequently "split borrow"), you need to:
save the guard (returned by lock) in a separate value, as the lock needs to live as long as the value is accessed.
extract the value as &mut from the guard with MutexGuard::deref_mut.
Here's an updated func_1:
use std::ops::DerefMut;
fn func_1(mtx: &Mutex<MyObject>) {
let mut guard = mtx.lock().unwrap();
let obj = guard.deref_mut();
let a = &mut obj.a;
let b = &mut obj.b;
*a += 1;
*b *= 2;
}
Getting the below error when trying to push more elements to a vector. How to overcome this error
error[E0506]: cannot assign to `x` because it is borrowed
x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
| ^^ assignment to borrowed `x` occurs here
76 | core_regex_dict.push(&x);
| --------------- --- borrow of `x` occurs here
| |
| borrow later used here
Code:
let mut x = String::new();
for ts in test_list {
x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
core_regex_dict.push(&x);
}
It's hard to answer your question because you didn't give us enough information. In particular, we need to know how core_regex_dict is defined. I'm assuming that core_regex_dict has type Vec<&str>. You need to change that to Vec<String>:
let core_regex_dict = Vec::new(); // No need to specify the item type, it will be inferred.
// No need to declare `x` before the loop unless you need to use the
// last value afterward...
for ts in test_list {
let x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
core_regex_dict.push (x); // No `&` -> we push the String itself instead of a reference
}
Found a solution that involves leaking the memory of the String in https://stackoverflow.com/a/30527289/12323498
But, is there a better way to achieve this without leaking the memory?
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
and the code look like this now
let mut s = String::new();
for ts in test_list {
s = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
let s: &'static str = string_to_static_str(s);
core_regex_dict.push(s);
}
In the context of a crypto problem, to decrease verbosity, I'm "naming" a slice of v as block, doing some stuff to it, but then trying to verify the result of do_stuff on the whole of v:
fn x() {
let mut v = vec![0; 32];
let block = &mut v[0..16];
do_stuff(block);
check_stuff(&v);
do_stuff(block);
}
fn do_stuff(_: &mut [i32]) {}
fn check_stuff(_: &[i32]) {}
The borrow checker complains:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/lib.rs:6:17
|
3 | let block = &mut v[0..16];
| - mutable borrow occurs here
...
6 | check_stuff(&v);
| ^^ immutable borrow occurs here
7 | do_stuff(block);
| ----- mutable borrow later used here
I'm aware of the kind of guarantee this is trying to provide. However, assuming I know what I'm doing, is there an idiomatic way to give a name to the slice without having to use do_stuff(&mut v[0..16]) or having to make copies every time?
Why does the compiler reject this code:
struct S<'a> {
i: i32,
r: &'a i32,
}
fn main() {
let mut s = S{i: 0, r: &0};
{
let m1 = &mut s;
m1.r = &m1.i;
}
let m2 = &mut s;
}
The error is: "cannot borrow s as mutable more than once at a time" (first borrow: m1, second borrow: m2).
Why is the first borrow of s still alive after m1 goes out of scope?
I read about borrow scope extension beyond the scope of the original borrower. However, this always seemed to involve another borrower outside the scope of the original borrower that "took over" the original borrow, e.g. this code fails with the exact same error, which is clear to me:
fn main() {
let mut s = 0;
let r: &mut i32;
{
let m1 = &mut s;
r = m1;
}
let m2 = &mut s;
}
In the first example, if I replace m1.r = &m1.i; with m1.r = &dummy; (dummy defined as some &i32) or with let dummy = &m1.i;, the code compiles. The error occurs only if I store a reference to a field in another field of the borrowed struct. I don't see why this should extend the borrow beyond its scope.
My best guess as to what is wrong with the code is:
s.r's original lifetime is the whole of main,
when I assign a reference to m1.r it has to be that original lifetime, but &m1.i is only valid for as long as m1 lives.
But I might be wrong (the error message would be misleading then).
First note that
let mut s = S{i: 0, r: &0};
{
s.r = &s.i;
}
let m2 = &mut s;
Gives
cannot borrow `s` as mutable because `s.i` is also borrowed as immutable
Hopefully this should be clear - if a struct self-borrows then it is borrowed. This points out why any self-borrowing structure is basically useless - it cannot be moved (invalidating its own pointer) nor can and mutable reference be taken to it.
Next one needs to understand that immutable references from mutable references count as borrows into the mutable reference, so extend it. For example
let mut v = ();
let r1 = &(&mut v);
let r2 = &v;
gives
cannot borrow `v` as immutable because it is also borrowed as mutable
It's not clear if this is legally able to be a new borrow into the original structure, but it as-yet does not act as such.