Compiling playground v0.0.1 (/playground)
warning: value passed to `s1` is never read
--> src/main.rs:8:16
|
8 | fn example(mut s1: &mut String) {
| ^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` on by default
error[E0597]: `s2` does not live long enough
--> src/main.rs:10:10
|
8 | fn example(mut s1: &mut String) {
| - let's call the lifetime of this reference `'1`
9 | let mut s2 = String::from("abc");
10 | s1 = &mut s2; // error: `s2` does not live long enough
| -----^^^^^^^
| | |
| | borrowed value does not live long enough
| assignment requires that `s2` is borrowed for `'1`
...
13 | }
| - `s2` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` due to previous error; 1 warning emitted
If I inline the function like this:
let mut s = String::from("abc");
{
let mut s1: &mut String = &mut s;
let mut s2 = String::from("abc");
s1 = &mut s2; // no error here
dbg!(&s1);
};
Here, s1 is of type &'a mut String, where lifetime 'a must be longer than the function runs.
Here, s1 is of type &'b mut String, where 'b lasts at least until after the line where dbg!(&s1) appears, but at most until the end of the block (which is the same position in your example). When you write &mut s2, the lifetime of that expression can be made to match the lifetime of s1.
If you are trying to change what the mutable reference points to (sometimes called an "out parameter" of the function), then the code you want is *s1 = s2; instead of s1 = &mut s2;.
I think I understand my mistake now. I was under the impression that s1 was part of example scope.
But this not the case.
A more correct inline conversion for example is probably this:
let mut s = String::from("abc");
{
let mut s1: &mut String = &mut s;
{
let mut s2 = String::from("abc");
s1 = &mut s2;
dbg!(&s1);
};
dbg!(&s1);
}
The binding s1 is within the function scope. However, the value stored in that variable (and thus the type of s1, which is &'a mut String) has a lifetime 'a that may go beyond the function scope.
This may become more obvious when you desugar the function:
fn example<'a>(mut s1: &'a mut String) {
let mut s2 = String::from("abc");
s1 = &mut s2; // error: `s2` does not live long enough
dbg!(&s1);
}
Ok, so the inferred 'a lifetime is still tied to s1 even if I declared it as mut. Are there any useful examples for declaring a function argument of type &Something or &mut Something as a mutable bidding?
You often see that pattern when subslicing into a slice repeatedly in a loop. For a trivial example, this function strips all instances of [1] and [2, 3] off the start of its input slice, returning a subslice: