go4fun.fun
Go4Fun - Fun Interview Puzzles

Follow

Go4Fun - Fun Interview Puzzles

Follow
Rust: Mutable/Immutable variables & reference types

Rust: Mutable/Immutable variables & reference types

go4fun.fun's photo
go4fun.fun
·Nov 15, 2022·

4 min read

One topic that is causing a lot of confusion for Rust new-joiners is a difference between immutable/mutable variables and immutable/mutable references types.

We are going to break down each below case and consider it separately, with examples:

Immutable variable bound to a value (let t: T = v)

// [Example 1]:
let t: i32 = 1;        
t = 2; //compilation error: cannot assign twice to immutable variable `t1`

// [Example 2]:
struct A { a: i32}
let t1: A = A {a:1};        
t1 = A {a:2}; //compilation error: cannot assign twice to immutable variable `t`
t1.a = 3; //compilation error: cannot assign to `t1.a`, as `t1` is not declared as mutable

In the first example, a variable t was declared as immutable (was not explicitly marked as mutable), so it was not possible to re-bind it to a new value 2. Similarly, in the second example, it was not possible to re-bind an immutable variable t1 to a new structure value A {a: 2}. And also, since t1 was declared immutable, it was not possible to update a structure field t1.a to a new value 3.

Mutable variable bound to a value (let mut t: T = v)

// [Example 1]:
let mut t: i32 = 1;        
t = 2; //compiles OK

// [Example 2]:
struct A { a: i32 }
let mut t1: A = A {a:1};        
t1 = A {a:2}; //compiles OK
t1.a = 3; //compiles OK

In the first example, a variable t was declared as mutable, so it was possible to re-bind it to a new value 2. Similarly, in the second example, a mutable variable t1 was bound to a structure value A {a:1}, and then it was possible to re-bind the variable to a new structure value A {a:2}. Also, it was possible to mutate the field t1.a inside the structure to a new value 3.

Immutable variable bound to Immutable reference (let t: &T = &v)

let t: &i32 = &1;        
t = &2; //compilation error: cannot assign twice to immutable variable `t`        
*t = 2; //compilation error: cannot assign to `*t`, which is behind a `&` reference

A variable t was declared as immutable, so it was not possible to re-bind it to a new immutable reference &2 (a new immutable reference pointing to another value 2). Also it was not possible to update the actual referent value *t via the reference t, because the reference t was itself defined as immutable &i32.

Immutable variable bound to Mutable reference (let t: &mut T = &mut v)

let t: &mut i32 = &mut 1;        
t = &mut 2; //compilation error: cannot assign twice to immutable variable `t` 
*t = 2; //compiles OK

A variable t was defined as immutable (even though it was bound to a mutable reference &mut 1), so it was not possible to re-bind it to a new mutable reference &mut 2 (a new mutable reference pointing to another value 2). But it was OK to update the actual referent value *t via the reference t, because the reference t was itself defined as mutable &mut i32.

Mutable variable bound to Immutable reference (let mut t: &T = &v)

let mut t: &i32 = &1;                
t = &2; //compiles OK  
*t = 2; //compilation error: cannot assign to `*t`, which is behind a `&` reference

A variable t was declared as mutable, so it was possible to re-bind it to a new immutable reference &2 (a new immutable reference pointing to another value 2). But it was not possible to update the actual referent value *t via the reference t, because the reference t was itself defined as immutable &i32.

Mutable variable bound to Mutable reference (let mut t: &mut T = &mut v)

let mut t: &mut i32 = &mut 1;        
let new_t: &mut i32 = &mut 2;        
t = new_t; //compiles OK
*t = 2; //compiles OK

A variable t was declared as mutable, so it was possible to re-bind it to a new mutable reference &mut 2 (a new mutable reference pointing to another value 2). In this case, we had to bind &mut 2 to another variable new_t first, because assigning it directly to t would cause a compilation error temporary value is freed at the end of this statement. Also it was OK to update the actual referent value *t via the reference t, because the reference t was itself defined as mutable &mut i32.

 
Share this