Rust's references do not work like they would in other languages like C/C++/Java. The Rust compiler ensures memory safety at compilation time, and it does so through the use of the "borrow checker". The borrow checker adheres to a set of rules, and the code you posted violates one of them.
Here's a direct quote from the Rust book that addresses this exact situation:
- At any given time, you can have either one mutable reference or any number of immutable references.
First you create a mutable variable s1
, and borrow it as an immutable via s2
. This is fine, so long as you're not using both of them simultaneously. The problem doesn't occur here, because you haven't really done anything with the references yet. The problem occurs when you force these two references to be active at the same time. This happens when you access s1
before s2
goes out of scope(that would be after it's last use). Take a look at this:
let mut s1 = String::from("hello"); // -- Start of s1 scope --
let s2 = &mut s1; // -- Start of s2 scope --
s2.truncate(2); // s1 may not be used here as
// that breaks the rules
print!("{}", s1); // -- End of s1 scope --
println!("{}", s2); // -- End of s2 scope --
As you can see, due to the way your code is structured, the scopes of s1
and s2
must be active at the same time. If you were to swap the last two lines of code, changing your code into this:
let mut s1 = String::from("hello"); // -- Start of s1 scope --
let s2 = &mut s1; // -- Start of s2 scope --
s2.truncate(2); // s1 may not be used here as
// that breaks the rules
println!("{}", s2); // -- End of s2 scope --
print!("{}", s1); // -- End of s1 scope --
Then your code would compile and run as expected. The reason is that while s2
's scope is active, you're not using s1
at all. In other words, these things happen at every line of the above code:
s1
owns newly the created String
s2
mutably borrows the String
s2
is used to truncate the String
s2
is used to print the String
. Since this is the last use of s2
, after this line ownership of the String
goes back to s1
.
s1
is used to print the String
.
I hope this clarifies the situation for you.
I'd suggest that you take the time to look at the Rust book's "Understanding Ownership" chapter here. My advice would be to go through the whole book starting from the beginning. It will give you a very good understanding of Rust as a language and its ecosystem.