Reputation: 105
I am reading the official Rust Book and looking at listing 4-8 in Section 4.3.
The code looks like this:
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear();
}
This line:
let word = first_word(&s);
seems to borrow an immutable reference to s
. (This is where I guess I'm wrong; I just don't know why.)
In the next line, we mutate s
by calling the clear()
method.
I was expecting the compiler to throw:
cannot borrow `s` as mutable because it is also borrowed as immutable
Why does this compile?
Upvotes: 3
Views: 78
Reputation: 93274
The string s
is immutably borrowed for the duration of the call to first_word
. As soon as the control is returned to main
after first_word
, the string is not considered borrowed anymore and can be mutated as you have observed.
If first_word
were to return a &String
which you extended the lifetime of by assigning it to a variable, then you would see the error you expected. E.g.
fn first_word(s: &String) -> &String {
&s
}
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear();
}
cannot borrow
s
as mutable because it is also borrowed as immutable
https://rust.godbolt.org/z/cMVdVf
In that case, adding an extra scope would fix that:
fn main() {
let mut s = String::from("hello world");
{
let word = first_word(&s);
}
s.clear();
}
Upvotes: 5