The following program_pass compiles in Rust.
fn main() {
let mut x = 0;
let mut y = &mut x;
let mut z = &mut y;
let mut last = &mut z;
let mut alt_y = &mut x;
let mut alt_z = &mut alt_y;
z = &mut alt_y; // *last = &mut alt_y;
}
The following program_error does not.
fn main() {
let mut x = 0;
let mut y = &mut x;
let mut z = &mut y;
let mut last = &mut z;
let mut alt_y = &mut x;
let mut alt_z = &mut alt_y;
*last = &mut alt_y; // z = &mut alt_y;
}
What is violated in program_error, while not in program_pass?
Just started, but this is really going against what I thought to be my understanding of Rust.
It's not inconsistency, it is is a intended behavior instead.
In first case, no mutable reference is being used. Effectively no issue, so rust compiler is happy.
In second case the rust compiler sees that mutable reference last is being dereferenced so it is taken as value access. And as we know rust doesn't allow the two mutable borrows.
Reference: Deref
To prove my point have tweaked your program a bit
fn main() {
let mut x = 0;
let mut y = &mut x;
let mut z = &mut y;
let mut last = &mut z;
let mut alt_y = &mut x;
let mut alt_z = &mut alt_y;
// notice the RHS here assigning
// mutable reference of i32 literal
*last = &mut &mut 4;
// ^ not related to x anyhow
}
And now the error will reveal the reason behind the issue\
error[E0499]: cannot borrow `x` as mutable more than once at a time
--> src/main.rs:7:21
|
3 | let mut y = &mut x;
| ------ first mutable borrow occurs here
...
7 | let mut alt_y = &mut x;
| ^^^^^^ second mutable borrow occurs here
...
11 | *last = &mut &mut 4;
| ------------------- first borrow later used here
Related
Can someone explain the following, please?
this compiles (explanation: NLL y not referenced after initial definition?)
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x;
println!("z: {}", z);
}
this doesn't compile (explanation: z not referenced but only introduced the line before so still active?)
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x;
println!("y: {}", y);
}
this compiles (explanation: NLL z not referenced after initial definition?)
fn main() {
let mut x = 5;
let z = &mut x;
let y = &x;
println!("y: {}", y);
}
this doesn't compile (just to see whether introducing lines would lead to z not being active by the println)
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x;
let foo = String::from("foo");
println!("y: {}, foo: {}", y, foo);
}
I'm confused... I couldn't find anything that covers this specific case in the book but if somebody has a link to something that explains this behaviour, I would appreciate it.
fn main() {
let mut x = 5;
let y = &x;
// 'y lifetime starts, holding an immutable reference to x
// 'y lifetime ends (never used later), releasing hold on x
let z = &mut x; // this is fine because the hold is released
println!("z: {}", z);
}
fn main() {
let mut x = 5;
let y = &x;
// 'y lifetime starts, holding an immutable reference to x
let z = &mut x; // this is forbidden because of the existing hold
println!("y: {}", y);
// 'y lifetime ends, releasing hold on x
}
fn main() {
let mut x = 5;
let z = &mut x;
// 'z lifetime starts, holding a mutable reference to x
// 'z lifetime ends (never used later), releasing hold on x
let y = &x; // this is fine because the hold is released
println!("y: {}", y);
// 'y lifetime ends, releasing hold on x
}
Pretty much the same as #2
fn main() {
let mut x = 5;
let y = &x;
// 'y lifetime starts, holding an immutable reference to x
let z = &mut x; // this is forbidden because of the existing hold
let foo = String::from("foo");
println!("y: {}, foo: {}", y, foo);
// 'y lifetime ends, releasing hold on x
}
As you know, no other references can exist while a mutable reference to some data also exists. You will see &mut also called "exclusive references" for this reason.
The borrow checker is what enforces this, using the lifetimes of the references in your code. In older versions of Rust, all lifetimes were "lexical" - they would last as long as their containing scope. "Non-lexical lifetimes" were introduced to make things easier for the programmer, by making it so reference lifetimes would only last as long as those references were used.
This is what allows examples #1 and #3 to work. A reference is created but the lifetime immediately ends because they aren't used later, so there is no overlap of lifetimes when the next line creates a different reference.
It's useful to look at the lifetime of every variable here. Let's look example by example.
// example one
fn main() {
let mut x = 5;
let y = &x; // y is declared here, but never used
// so its lifetime is effectively nil
let z = &mut x; // by this line, it no longer exists
println!("z: {}", z);
}
// example two
fn main() {
let mut x = 5;
let y = &x; // y is declared here and used in the
// println, so...
let z = &mut x; // ...this is invalid, since you cannot
// take a mutable reference when you have
// an existing reference.
println!("y: {}", y);
}
// example three
fn main() {
let mut x = 5;
let z = &mut x; // z is declared here but never used
// so its lifetime is effectively nil
let y = &x; // by this line, it no longer exists
println!("y: {}", y);
}
// example four
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x; // This is functionally identical to ex. 2
let foo = String::from("foo");
println!("y: {}, foo: {}", y, foo);
}
I am trying to write a mem::swap function without using any std lib functions. i am totally new to rust and still trying to make sense of how to use rust language.
below is my code
fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
let mut t: &mut T = y;
y = x;
x = t;
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
let mut t = Box::new(0);
swap(&mut x, &mut y);
}
and i am facing below error
error: lifetime may not live long enough
--> src/main.rs:4:29
|
1 | fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
| - - let's call the lifetime of this reference `'2`
| |
| let's call the lifetime of this reference `'1`
...
4 | let mut t: &mut T = y;
| ^ assignment requires that `'2` must outlive `'1`
|
help: consider introducing a named lifetime parameter
|
1 | fn swap<'a, T: std::fmt::Display>(x: &'a mut T, y: &'a mut T) {
| +++ ++ ++
what does 'lifetime may not live long enough' mean ?
is there a simple way to write mem::swap code in rust ?
You need to Copy the data. The reference you're using is useless for this purpose. You need to actually alter what both x and y reference.
For example:
fn swap<T>(a: &mut T, b: &mut T) where T : Copy {
(*a,*b) = (*b, *a)
}
fn main() {
let mut a = 1;
let mut b = 2;
swap(&mut a,&mut b);
println!("a={}, b={}", a, b);
}
If you set up the conditions here, it's really a one-liner, Rust will figure out the "temporary" stuff for you. In fact, having a function to do this is actually kind of overkill, since you can just do that single line anywhere in your code as you would normally.
Maybe you want to optimize this around boxed values, taking Box<T> as an argument instead, in which case you could swap references within the box instead of copying, but that's a specialization.
How about using core::ptr::swap to swap raw pointers *mut T.
use core::ptr::swap;
fn custom_swap<T>(x: &mut T, y: &mut T) {
unsafe {
(x as *mut T).swap(y as *mut T);
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
println!("x={}, y={}", x, y);
custom_swap(&mut x, &mut y);
println!("x={}, y={}", x, y);
}
output
Hello, world!
x=5, y=42
x=42, y=5
When pattern-matching, you can specify that you'd like to get a mutable reference to the contained value by using ref mut:
let mut score = Some(42);
if let Some(ref mut s) = score {
&mut s;
}
However, the inner value is not mutable:
error[E0596]: cannot borrow immutable local variable `s` as mutable
--> src/main.rs:4:14
|
4 | &mut s;
| ^
| |
| cannot reborrow mutably
| try removing `&mut` here
I tried to add in another mut, but that was not valid:
if let Some(mut ref mut s) = score {
&mut s;
}
error: the order of `mut` and `ref` is incorrect
--> src/main.rs:3:17
|
3 | if let Some(mut ref mut s) = score {
| ^^^^^^^ help: try switching the order: `ref mut`
error: expected identifier, found keyword `mut`
--> src/main.rs:3:25
|
3 | if let Some(mut ref mut s) = score {
| ^^^ expected identifier, found keyword
error: expected one of `)`, `,`, or `#`, found `s`
--> src/main.rs:3:29
|
3 | if let Some(mut ref mut s) = score {
| ^ expected one of `)`, `,`, or `#` here
Not a direct answer, but possible workarounds
Create an intermediate variable
if let Some(ref mut s) = score {
let mut s = s;
&mut s;
}
#[derive(Debug)]
struct X;
enum Foo<T> {
Bar(T),
_Baz,
}
fn main() {
let mut score = Foo::Bar(X);
if let Foo::Bar(ref mut s) = score {
//let x = s;
//println!("{:?}", **x); ! not possible
let x = &mut &mut *s; // &mut &mut X
println!("{:?}", **x);
}
}
For Option specifically
if let Some(ref mut s) = score.as_mut() {
s; //:&mut &mut i32
}
if let Some(mut s) = score.as_mut() {
&mut s;
}
Below code may give an idea for the possible solution to the problem. It's just a sample & testable code to provide a tiny example that aimed at the issue. Of course it may not cover the whole intents and purposes.
fn main() {
let mut score = Some(42i32);
let res = if let Some(41) = score {
println!("41 is matched");
1i32
} else if let Some(ref mut s) = score { //&mut score {
//let mut s2 = s;
//println!("s: {:#?}", s);
test(&mut &mut *s); // This part may be like this for borrowing
//println!("s: {:#?}", s);
1i32
} else {
0i32
};
//println!("Result: {:#?}", score);
assert_eq!(res, 1i32);
}
fn test(ref mut s: &mut &mut i32) -> i32 {
//let mut s2 = s;
return test2(&mut *s);
}
fn test2(n: &mut i32) -> i32 {
*n += 1;
//println!("Value: {}", *(*n));
return *n;
}
Live Version: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3e7e1ee712a31f74b201149365035f
Gist Link: https://gist.github.com/7c3e7e1ee712a31f74b201149365035f
I have found a case where manually inlining a function changes the way the borrow-checker treats it, such that it no longer compiles. Presumably it is relying on the information in the function signature. How can I provide this information in the inlined version?
How I think it's working
Let 'a and 'b be lifetimes with 'a shorter than 'b (which can be written 'b: 'a).
Suppose I have a p: &'b mut f32. I can borrow p briefly (with &mut p) to obtain q: &'a mut &'b mut f32.
Have I correctly understood that &'a mut &'b mut f32 is equivalent to &'a mut &'a mut f32 because 'b: 'a?
I can then dereference q (with *q) to obtain r: &'a mut f32. I can write to the f32 via r (with *r = something), and I can later (outside lifetime 'a) read back the value via p (with *p).
With a function call
Here is some working code that I think uses the above sequence:
fn reborrow<'a, 'b: 'a>(q: &'a mut &'b mut f32) -> &'a mut f32 {
*q
}
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = reborrow(q);
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
(Replacing *q with q in the body of reborrow() also works, because Rust inserts the necessary dereference if it is missing).
Manually inlined
If I manually inline the reborrow() call, it no longer compiles:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = *q; <-- ERROR REPORTED HERE.
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
error[E0507]: cannot move out of borrowed content
Who took away my toys? What is the type inference thinking/missing?
Can I annotate the let binding somehow to make the compiler infer the same types as in the previous version?
Some other attempts
Here's another version that works, but which doesn't define the name r:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
**q = 2.718;
}
assert_eq!(*p, 2.718);
}
Here's a work-around that defines the name r and works, but does not use the same sequence of borrows and dereferences:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r = &mut **q;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
I made a playground combining all four versions.
The obvious solution works, as one could expect:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let r: &mut f32 = p;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
It seems relatively intuitive and is what I would expect a newcomer to end up with.
If you start thinking about it, however, it will not make sense. As described, it looks like:
let r: &mut f32 = p; moves out of p
and yet we use p later in assert_eq!(*p, 2.718);
A reasonable explanation would be that p is Copy, however it's not1!
The answer is that, implicitly, Rust is performing a re-borrowing behind the scenes. That is, the explicit code is:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let r: &mut f32 = &mut *p;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
We can check this by attempting to read p after re-borrowing it, and check the compiler error:
error[E0502]: cannot borrow `p` as immutable because `*p` is also borrowed as mutable
--> <anon>:6:24
|
5 | let r: &mut f32 = p;
| - mutable borrow occurs here
6 | println!("{}", p);
| ^ immutable borrow occurs here
7 | *r = 2.718;
8 | }
| - mutable borrow ends here
error: aborting due to previous error
Which confirms that p is indeed only borrowed mutably, and not moved, cloned or copied.
1 A mutable reference cannot be Copy or even Clone as it would violate the Aliasing XOR Mutability principle which underpins Rust safety.
I can't possibly begin to explain this, but you can do a similar trick as the implicit dereference and say that r is &mut f32:
fn main() {
let mut x: f32 = 3.142;
let mut p = &mut x;
{
let q = &mut p;
let r: &mut f32 = q;
*r = 2.718;
}
assert_eq!(*p, 2.718);
}
I have an Option<&mut T> and want to access the contained reference multiple times, like so:
fn f(a: Option<&mut i32>) {
if let Some(x) = a {
*x = 6;
}
// ...
if let Some(x) = a {
*x = 7;
}
}
fn main() {
let mut x = 5;
f(Some(&mut x));
}
That doesn't work, because if let Some(x) = a moves the reference value out of the Option, and the second if let Some(x) = a will result in a compiler error. Without the second if let ..., this works flawlessly, so a doesn't have to be mutable.
The following:
if let Some(ref x) = a {
**x = 6;
}
gives an error: "assignment into an immutable reference".
This would work:
fn f(mut a: Option<&mut i32>) {
if let Some(ref mut x) = a {
**x = 6;
}
if let Some(ref mut x) = a {
**x = 7;
}
}
The mut a is necessary, otherwise I get an error "cannot borrow immutable anonymous field (a:std::prelude::v1::Some).0 as mutable". But this feels wrong: a shouldn't have to be mutable, because I'm not modifying it (see above).
What's the correct solution?
Edit 1
My problem is different from the one in How to pass `Option<&mut ...>` to multiple function calls without causing move errors?. I want to mutably dereference the reference in an Option<&mut T> multiple times, while the other one wants to pass an Option to multiple function invocations. The solutions to the other question are not applicable to my situation.
What about this?
fn f(a: Option<&mut i32>) {
if let Some(&mut ref mut x) = a {
*x = 6;
}
// ...
if let Some(&mut ref mut x) = a {
*x = 7;
}
}
In this case, a doesn't need to be mutable.
The &mut ref mut feels a bit awkward, but it makes sense: first we remove a &mut by destructuring and then take a mutable reference to the value again. It's more obvious when we don't use the Option:
let mr: &mut Vec<u32> = &mut vec![];
{
let &mut ref mut a = mr;
a.push(3);
}
mr.push(4);
This also works. The third (special) line is equivalent to:
let a = &mut *mr ;
// ^^^----- this is an lvalue of type `Vec<u32>`
// ^^^^^^^^^^^^----- together it's of type `&mut Vec<u32>` again
In the Option case, we can't use the &mut *X version, but need to do all of it inside of the pattern. Thus the &mut ref mut x.