Mutable Borrowing: The One Exclusive Borrower
Level: intro (score: 1)
Rust enforces strict borrowing rules to prevent data races and ensure memory safety.
A variable can have multiple immutable references (&T
), or one mutable reference (&mut T
)—but never both at the same time.
Why This Matters
In Python, variables are mutable by default, so you can modify a value even when multiple references exist:
def append_exclamation(text):
text += "!"
return text
word = "Hello"
new_word = append_exclamation(word)
print(word) # Still "Hello" (strings are immutable)
print(new_word) # "Hello!"
However, Rust enforces stricter rules:
-
If you borrow mutably (
&mut
), no other references (mutable or immutable) can exist at the same time. -
If you borrow immutably (
&
), multiple references are allowed, but you cannot modify the data.
Task
Implement the function: to_uppercase(text: &mut String)
-
The function should take a mutable reference to a String.
-
It should modify the string in place, converting all characters to uppercase.
-
The function does not return anything—it should mutate the original value.
Hints
-
Use
.make_ascii_uppercase()
to modify the string in place. -
Note that Rust does not allow an immutable borrow to exist while a mutable borrow is active. Try to make a new project
cargo new dummy
and test this behavior by putting this code insrc/main.rs
:
fn main() {
let mut word = String::from("hello");
let ref1 = &word; // Immutable borrow
let ref2 = &word; // Another immutable borrow
word.push_str("!"); // ❌ ERROR: Mutable borrow while immutable borrows exist
println!("ref1: {}", ref1);
println!("ref2: {}", ref2);
// if removing the word.push_str("!") line, this code will compile
word.make_ascii_uppercase(); // ✅ Mutable borrow after immutable borrows are dropped
}
Mutability rules in Rust help eliminate data races and undefined behavior at compile time.
You’ll never have to deal with "race conditions" like in multi-threaded Python code! 💡
Happy coding! 🚀