In pattern matching, one can append &[&] [mut] to an identifier like &e in v.iter().filter(|&e| ...). This is called reference patterns.
When playing with this pattern, I found an inconsistent behavior:
For a doubly borrowed value, &&e works but &e also works.
When mutable, however, &&mut e works whilst &mut e doesn't work.
Why?
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
v.iter()
.filter(|e| *e * 2 >= 8)
.for_each(|e| println!("{}", e)); //=> 4 5
v.iter()
.filter(|e| **e * 2 >= 8)
.for_each(|e| println!("{}", e));
v.iter()
.filter(|&e| e * 2 >= 8)
.for_each(|e| println!("{}", e));
v.iter()
.filter(|&&e| e * 2 >= 8)
.for_each(|e| println!("{}", e));
//NG
// v.iter_mut()
// .filter(|&mut e| e * 2 >= 8)
// .for_each(|e| println!("{}", e));
v.iter_mut()
.filter(|&&mut e| e * 2 >= 8)
.for_each(|e| println!("{}", e));
}
Rust Playground
From a high level perspective:
&mut T is a mutable reference of type T and &&mut T is a immutable reference of &mut T.
From a compiler perspective: (ref)
The grammar production for reference patterns has to match the token
&& to match a reference to a reference because it is a token by
itself, not two & tokens.
Adding the mut keyword dereferences a mutable reference
Basically && points the immutable reference to a immutable reference if there is a mut, it dereferences to a mutable reference (immutable ref to mutable ref, i.e. as mentioned above).
When mutable, however, &&mut e works whilst &mut e doesn't work.
&mut e doesn't work because method filter from std::iter expects you to define a closure with immutable referenced parameter:
fn filter<P>(self, predicate: P) -> Filter<Self, P>
where
P: FnMut(&Self::Item) -> bool,
&&mut T pattern works because Self::Item is a &mut T since you are using iter_mut().
Rust Complier says : you can borrow multiple immutable references, but you
cannot borrow multiple mutable references in a defined scope.
let e = 23;
here we can borrow multiple immutable references of &e or reference of reference &&e and our code will not break, because compiler knows all the references are immutable, hence no one can change the value.
but, lets say we borrow a mutable reference of a reference &&mut e , here the problem is we have two mutable references of same object(I: &mut e, II: &&mut e) anyone can change the value of e, and as per rule we are not allowed to have two mutable references of same object in scope.
P.S. Please correct me if i'm wrong.
Related
This question already has an answer here:
What is lifetime elision in very simple terms?
(1 answer)
Closed 3 months ago.
I have this function that borrows two individual elements from a vector. It works as expected:
fn borrow_mut_two<T>(v: &mut [T], i: usize, j: usize) -> (&mut T, &mut T) {
assert!(i < j);
let (left, right) = v.split_at_mut(j);
(&mut left[i], &mut right[0])
}
fn test() {
let mut v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
let i = 2;
let j = 5;
let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
*ref_a += 1;
*ref_b += 5;
assert_eq!(*ref_a, i + 1);
assert_eq!(*ref_b, j + 5);
}
What I'm trying to understand is why the following code doesn't compile:
fn test() {
let mut v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
let i = 2;
let j = 5;
let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
// Added this line:
let (other_ref_a, other_ref_b) = borrow_mut_two(&mut v, i, j);
*ref_a += 1;
*ref_b += 5;
assert_eq!(*ref_a, i + 1);
assert_eq!(*ref_b, j + 5);
}
It seems it works in a safe manner, because it doesn't allow me to mutably borrow the same elements twice (or potentially other elements).
My question is how does the compiler know that this is unsafe (and therefore reject compiling it)?
The compiler errors are:
229 | let (ref_a, ref_b) = borrow_mut_two(&mut v, i, j);
| ------ first mutable borrow occurs here
230 | let (other_ref_a, other_ref_b) = borrow_mut_two(&mut v, i, j);
| ^^^^^^ second mutable borrow occurs here
As far as I know the return value of borrow_mut_two is the tuple (&mut T, &mut T), which may or may not be a borrow to self, but it seems the compiler does know it's borrowing self. My assumptions may be wrong though 🙂.
The only thing that comes to mind is that Rust automatically adds the lifetime:
fn borrow_mut_two<'a, T>(v: &'a mut [T], i: usize, j: usize) -> (&'a mut T, &'a mut T)
Which would mean that in my test function, 'a is still alive (i.e. self mutably borrowed) due to the first call to borrow_mut_two while the second call happens, and that's how it detects a second mutable borrow.
But I'd like to confirm if this is correct.
Extra
It could be related to this part of the book. The only difference I see is that my function returns a tuple. So the question can be reduced to: Does Rust's second lifetime elision rule also add 'a to each element of a tuple? If so, then my doubt is solved:
The first rule is that the compiler assigns a lifetime parameter to
each parameter that’s a reference. In other words, a function with one
parameter gets one lifetime parameter: fn foo<'a>(x: &'a i32); a
function with two parameters gets two separate lifetime parameters: fn
foo<'a, 'b>(x: &'a i32, y: &'b i32); and so on.
The second rule is that, if there is exactly one input lifetime
parameter, that lifetime is assigned to all output lifetime
parameters: fn foo<'a>(x: &'a i32) -> &'a i32.
Yes, your understanding is correct - due to lifetime elision, the following two function signatures are equivalent:
fn borrow_mut_two<T>(v: &mut [T], i: usize, j: usize) -> (&mut T, &mut T)
fn borrow_mut_two<'a, T>(v: &'a mut [T], i: usize, j: usize) -> (&'a mut T, &'a mut T)
Because the lifetimes of the output are tied to the lifetime of v, the compiler knows that v is still mutably borrowed until those derived references stop being used.
The issue in your second code is that you are trying to borrow mutably v while an other mutable borrow is still alive, just as the compiler indicates to you. To be more precise, the compiler sees the following constraints:
fn test() {
// ...
let (ref_a, ref_b) = borrow_mut_two(&'3 mut v, i, j); // ------+
// ^^^^^ ^^^^^ ^^^^^^^ Let's call // |
// +---+ this lifetime '3 // |
// | // |
// Let's call the lifetime of these mutable borrows '1 // |
// Added this line: // +- '1
let (other_ref_a, other_ref_b) = borrow_mut_two(&'4 mut v, i, j); // -+ '2 |
// ^^^^^^^^^^^ ^^^^^^^^^^^ // | |
// +------+ Let's call the lifetimes of these borrows '2 // -+ |
*ref_a += 1; // |
*ref_b += 5; // ------+
}
First of all, '3 and '4 cannot outlive the lifetime of v, but this isn't very important in this case so we can forget about it. Then, due to the signature of borrow_mut_two, '1='3 and '2='4. Furthermore, since we are talking about mutable borrows, there can be at most one at a time. Finally, I have indicated the minimum span of '1 and '2.
When the compiler tries to enforce all these constraints, it will fail, because clearly '1 and '2 cannot be disjoint while living at least for as much time as they are useful.
In fact, it is sometimes possible to make this kind of layout work, because '1 is never used when '2 is used, and '2's span is included in '1's. In these cases, the compiler says the borrows are stacked, and it could accept them if '2 was a reborrow of '1. It is logically the case, but split_at_mut prevents the compiler from understanding this because internally it uses unsafe code on which the compiler can't reason as easily as it would otherwise.
I'm having some trouble understanding the compiler error message for this code:
struct A {
b: B,
c: C,
}
struct B {
f: u32,
}
struct C {
f: u32,
}
fn foo(b: &mut B) -> &u32 { &b.f }
fn bar(c: &mut C) -> &u32 { &c.f }
fn quux(z: &mut A) -> u32 { z.b.f }
fn baz(a: &mut A) {
let x = foo(&mut a.b);
let y = bar(&mut a.c);
let z = quux(a); // equivalent to: quux(&mut *a)
println!("{} {}", x, y);
}
error[E0499]: cannot borrow `*a` as mutable more than once at a time
--> src/main.rs:22:18
|
20 | let x = foo(&mut a.b);
| -------- first mutable borrow occurs here
21 | let y = bar(&mut a.c);
22 | let z = quux(a);
| ^ second mutable borrow occurs here
23 | println!("{} {}", x, y);
| - 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 line 20 is mutably borrowing *a (as the compilation error asserts), then line 21 must also mutably borrow *a (How couldn't it? It's nearly identical to line 20 -- only difference is which field is borrowed), so by my reasoning the code should still fail to compile after deleting line 22; however, the code actually compiles just fine if I delete line 22. The fact that this would then compile seems to contradict the compiler's claim that &mut a.b results in a mutable borrow of *a.
x and y are immutable borrows, so if anything I would expect a compilation error regarding the overlapping scopes of the immutable x/y and the mutable borrow of *a in line 22 (otherwise quux could conceivably mutate a while we're borrowing its fields).
What knowledge am I likely missing that makes this error message confusing to me? If you're not surprised by this message, could you break down how you reason about this?
Some more thinking before I submitted this question:
I suppose the immutable references returned from foo and bar somehow extend the original mutable borrows of a.b and a.c (why that would be necessary, I don't know). If that's the case, maybe the way to see this is that &mut a.b and &mut a.c in turn extend the mutable borrow of *a. The error message says the first mutable borrow of *a occurs on line 20, but maybe the way to see this is:
The true first borrow of *a is when when the caller gives us the &mut A.
While the compiler suggests there's a mutable borrow of *a on line 20, this isn't exactly the case: the mut &a.b expression borrows (*a).b, but merely extends the existing borrow given to us (as opposed to being a new mutable borrow of *a).
The last point, but with respect to mut &a.c.
Insert the aforementioned reasoning of "extending borrows" wrt *a.
The call to quux then mutably borrows the *a a second time.
So maybe what the compilation error calls the initial borrow of *a is actually reporting the location of the expression responsible for extending the original *a borrow?
Line 20 does not conflict with 21 since they borrow different fields within a and therefore cause no collision.
The issue is that foo and bar return references that inherit the lifetime of the mutable reference. Even though they return immutable references, their lifetimes rely on the lifetime of the mutable borrow. So by requiring they live for a period of time, by extension the mutable borrow must do so as well. The compiler always takes the function signature on face value so it can not downgrade the initial mutable reference. If it did not, it could lead to issues if the function was modified later or if it contained unsafe code that relied on consuming a mutable reference for safety.
Here is a counter example where all of the function signatures remain the same. Since the compiler can not make assumptions on how quux and foo will use their values quux may make the references returned by foo or bar invalid.
struct A {
b: B,
c: C,
}
struct B {
f: Option<u32>,
}
struct C {
f: u32,
}
fn foo(b: &mut B) -> &u32 {
b.f.as_ref().unwrap()
}
fn bar(c: &mut C) -> &u32 { &c.f }
fn quux(z: &mut A) -> u32 {
z.b.f = None;
z.c.f
}
fn baz(a: &mut A) {
let x = foo(&mut a.b);
let y = bar(&mut a.c);
let z = quux(a);
println!("{} {}", x, y);
}
There are two issues here. First: why does let x = foo(&mut a.b); prevent you from doing let z = quux(a);, and second why does let x = foo(&mut a.b); not prevent you from doing let y = bar(&mut a.c);?
Why does let x = foo(&mut a.b); prevent you from doing let z = quux(a);?
This is due to the lifetime elision rules. You declared foo as:
fn foo(b: &mut B) -> &u32
Since you use references there must be a lifetime, but since you didn't specify one yourself the compiler assumes that all references have the same lifetime. In other words, the compiler rewrites your code as:
fn foo<'a>(b: &'a mut B) -> &'a u32
Which means that the returned value has the same lifetime as the mutable borrow, so the mutable borrow lasts until the println where you use the return value x, which prevents other borrows of a.b or a as a whole.
But then why does let x = foo(&mut a.b); not prevent you from doing let y = bar(&mut a.c);?
That's because the compiler is smart enough to realize that a.b and a.c are disjoint parts of a, which can be borrowed without conflict (in the same way that you can borrow different local variables simultaneously).
I am trying to understand what exactly happens when functions reborrow mutable references.
fn main() {
let mut a = String::new();
let mut b = String::new();
let aa = &mut a;
let c = my_fun(aa, &mut b);
let d = &mut a;
println!("{}", c);
}
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun. But due to the lifetime bound I created in the function signature the reborrow should live at least as long as &mut b exist. So the println force the reborrow to live until it.
Shouldn't this be throwing an error of use after free because the anonymous reborrow has only scope inside my_fun? Outside of this function this reference shouldn't be valid.
But the error I get is:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:7:13
|
5 | let aa= &mut a;
| ------ first mutable borrow occurs here
6 | let c = my_fun(aa, &mut b);
7 | let d = &mut a;
| ^^^^^^ second mutable borrow occurs here
8 | println!("{}", c);
| - first borrow later used
which would have made sense if the mutable reference was merely copied instead of reborrowed inside the function.
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.
It's not quite that.
Let's backtrack a bit: why reborrowing?
There is a fundamental difference between &T and &mut T: &T is Copy, whereas &mut T is not even Clone. The result is that &mut T can only be moved and therefore a call such as:
let x: &mut T = /*...*/;
func(x);
Would result in x being unusable after the call. The work-around would then be to introduce a temporary:
let x: &mut T = /*...*/;
let tmp = &mut *x;
func(tmp);
This temporary would re-borrow the pointee of x, and be consumed by func.
And... that's re-borrowing! The compiler has this "temporary" creation built-in purely for ergonomics!
With that in mind, let's go back to:
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.
Lifetimes are generally more a range than a point, and this is true here.
The lifetime of tmp in my example above is constrained in 2 ways:
It cannot be greater than that of x.
It cannot be less than that of func.
Which is another way of saying that it can be anything in between those bounds.
I believe you're overthinking "reborrowing" here.
The lifetime requirements you applied say that the thing being referenced by the return value will have at least the lifetime of the things being referenced by the parameters. That's true (and if it weren't provably true, this wouldn't compile). So there is no dangling reference possible.
There isn't a separate "reborrowed" reference. Borrowing is bookkeeping inside the compiler to keep track of lifetimes. There is no let x = &*aa step that actually occurs or is even particularly implied. This isn't like reference counting where memory actually changes at runtime.
Inside of my_fun, y is a reference that's scoped to the function. But the return value is scoped to the caller. (Functions would be impossible to use if this weren't true, having nothing to do with &mut.)
In Rust by Example, it says:
A ref borrow on the left side of an assignment is equivalent to an & borrow on the right side.
I thought these two for loops would be equivalent:
Compiles successfully:
let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
*i = *i + 1;
}
println!("{:?}", v2);
Does not compile:
let mut v1 = vec![1, 2, 3];
for ref mut i in v1 {
*i = *i + 1;
}
println!("{:?}", v1);
It seems v is moved:
error[E0382]: use of moved value: `v1`
--> src/main.rs:6:22
|
3 | for ref mut i in v1 {
| -- value moved here
...
6 | println!("{:?}", v1);
| ^^ value used here after move
|
= note: move occurs because `v1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
What you quote from the book is a rule for normal assignments such as those by let. For example:
let x = &42;
let ref x = 42;
But the name binding in a for loop is a bit different:
The value to be looped around is converted into an iterator (<v1 as IntoIterator>::into_iter()) Lets call the result of that it.
Then the it.next() is called repeatedly:
If it returns Some(_) then the value of that is bound to your variable. Just as if you wrote let Some(ref mut i) = it.next() or let Some(mut i) = it.next(). Here is where the ref matters.
If it returns None the loop ends.
So in the for loop case, the ref and the & are not equivalent.
When you use the & at the right side of a loop, it does not change the binding of the variable directly; you just change the type of the object iterated. Then, all comes down to the implementation of IntoIterator for Vec<_> vs that for &Vec<_>.
If you iterate Vec<T>, it takes ownership of the vector and the iteration returns the values themselves. So for i in v1 consumes the vector and the i has the type of the contained values T.
If you iterate &Vec<T>, it borrows the vector and the iteration return pointers to the contained values &T, so in for i in &v1 the type of i is actually a pointer to the values. The same effect can be got with for i in v1.iter().
If you iterate &mut Vec<T>, is just like the previous one but mutable, so the iteration returns values of type &mut T.
The conclusion is that using ref in a for loop is not probably so useful.
In section 3.2 of the Nomicon, under the heading "liveness", it says
However it's often the case that Rust isn't sufficiently smart to
prove that multiple borrows are disjoint.
What is an example where the Rust compiler cannot prove that they are disjoint? Will this ever occur in a tuple struct?
The key is in the previous sentence:
Rust explicitly enables [reborrowing into multiple mutable references] to be done with disjoint struct fields, because disjointness can be statically proven
Outside of this case, the compiler cannot tell that two borrows are disjoint. In practice, this means that the compiler cannot tell that borrows resulting from a function call will be disjoint.
struct Thing {
a: i32,
b: i32,
}
fn example_works(thing: &mut Thing) {
let a = &mut thing.a;
let b = &mut thing.b;
}
fn get_a(thing: &mut Thing) -> &mut i32 {
&mut thing.a
}
fn get_b(thing: &mut Thing) -> &mut i32 {
&mut thing.b
}
fn example_doesnt_work(thing: &mut Thing) {
let a = get_a(thing);
let b = get_b(thing);
println!("{}, {}", a, b);
}
error[E0499]: cannot borrow `*thing` as mutable more than once at a time
--> src/lib.rs:26:19
|
25 | let a = get_a(thing);
| ----- first mutable borrow occurs here
26 | let b = get_b(thing); // cannot borrow `*thing` as mutable more than once at a time
| ^^^^^ second mutable borrow occurs here
27 | println!("{}, {}", a, b);
| - first borrow later used here
Will this ever occur in a tuple struct?
Not specifically because it's a tuple struct, but yes, it can happen for the same reasons. If you obtain a borrow from a function call, you will get the same problem as a "traditional" struct.