Page Content

Tutorials

What is mutable reference in rust ?

In Rust, variables are associated with names identify specific memory locations. They are  declared using the let statement. By default, variables declared with let are immutable. This means once a value is bound to the variable name, its value cannot be changed directly. The compiler guarantees that an immutable value will not change, which can make code easier to reason about.

However, mutability can be quite useful. To make a variable mutable, you add the mut keyword before the variable name in the let declaration. This also signals to anyone reading the code that the variable’s value might change.

Check here Installation procedure of Rust on Windows

Example:

Here’s an example of a mutable variable and assignment.

fn main(){
let mut Seial_Number_a = 10; // declares a mutable value
Seial_Number_a = 15;         // allowed because Seial_Number_a is mutable
}

If Seial_Number_a had not been declared with mut, the assignment Seial_Number_a = 15; would not compile.

Mutability with References

References in Rust also default to being immutable. They are created using the & operator. A reference lets you access data owned by another value without taking ownership of it.

What is &i32 in the Rust Mutability?

&i32 denotes a specific type in Rust. It refers to a value of type i32. In terms of mutability, the type &i32 represents a shared reference. Shared references let you see the value they point to but not change it. This means that if you have a variable of type &i32, the value it refers to is considered immutable. Multiple shared references (&i32) to the same value can exist concurrently.

Example:

fn main(){
let Seial_Number_a = 10; // An i32 value
let ref_a: &i32 = &Seial_Number_a; // ref_a is a shared reference to Seial_Number_a
// You can read the value through ref_a using the dereference operator *
println!("The value is: {}", *ref_a); // Output: The value is: 10
}

But you CANNOT change the value through ref_a because it’s a shared reference

//*ref_a = 15; // This line would cause a compile error

With references, there are two things that can be mutable:

  1. The reference itself.
  2. The referenced value.

To make a reference mutable (which allows it to be reassigned to point to a different value), you place mut before the variable name in the let binding:

fn main(){
let mut Seial_Number_a = 10; // a mutable variable
let mut Seial_Number_b= 20; // another mutable variable
let mut ref_a: &i32 = & Seial_Number_a; // ref_a is a mutable reference to an immutable value (&i32)
ref_a = & Seial_Number_b; // This is allowed because ref_a is mutable; it can be changed to reference Seial_Number_b
println!("The value is: {}", *ref_a);
}

In this case, the reference ref_a can be changed to point to Serial_Number_b, but because the type of the referenced value is &i32 (immutable), you cannot change the value through ref_a. Trying to do *ref_a = 30; would cause a compile error because the value referenced is immutable. The * operator is used for dereferencing, which means accessing the value that a reference points to.

To make the referenced value mutable (allowing you to change the value it points to through the reference), you use mut in the reference type: &mut T. To create such a reference, you need the &mut operator.

fn main(){
let mut Seial_Number_a = 10; // a mutable variable
let mut Seial_Number_b= 20; // another mutable variable
let mut ref_a: &mut i32 = &mut Seial_Number_a; // ref_a is a mutable reference to a mutable value (&mut i32)
// We can reassign the reference itself because 'ref_a' is declared with `mut`
ref_a = &mut Seial_Number_b; // Change ref_a to reference Seial_Number_b
// We can change the referenced value because the type is &mut i32
*ref_a = 30; // Dereference ref_a and update the value at Seial_Number_b
println!("The value is: {}", Seial_Number_b);
}

This example shows a reference ref_a that is declared with mut and points to a value via &mut i32. This allows both the reference itself (ref_a = &mut Seial_Number_b;) and the value it points to (*ref_a = 30;) to be changed. the first mut makes the variable p (the reference) mutable so it can be reassigned, while the mut in the type &mut i32 makes the referenced value mutable.

Limits to Mutable References

Rust’s safety guarantees include a critical rule about mutable references: at any given time, you can have either one mutable reference OR any number of immutable references to a particular piece of data in a specific scope. This rule prevents data races and inconsistencies.

Attempting to create multiple mutable references to the same value at the same time will result in a compile-time error:

fn main(){
let mut Seial_Number_a = 10; // a mutable variable
// This is OK: One mutable reference
let ref_a: &mut i32 = &mut Seial_Number_a;
// This will cause a compile error: Cannot borrow Seial_Number_a as mutable more than once
let ref_b: &mut i32 = &mut Seial_Number_a; // Error! Two mutable references to the same value
// Using ref_a after ref_b is declared would also be an issue depending on scope
*ref_a = 20; // If ref_b is in scope, this might also be problematic
println!("The value is: {}", Seial_Number_a);
}

The compiler’s “borrow checker” enforces these rules. Similarly, you cannot have both mutable and immutable references to the same value in the same scope.

While the general rules are strict, Rust offers advanced concepts like interior mutability, using types like RefCell<T>, which allow you to mutate data through immutable references by enforcing the borrowing rules at runtime instead of compile time.

You can Read also about the Rust Varibles

Index