I am working through the rustlings exercises and I ran into something i don't fully understand about lifetime. I will simplify the code to just the confusing part.
This function compiles correctly:
fn string_uppercase(mut data: &String) {
let newdata: &String = &data.to_uppercase();
}
this function doesnt
fn string_uppercase(mut data: &String) {
data = &data.to_uppercase();
}
and shows the following error:
error[E0716]: temporary value dropped while borrowed
--> exercises/06_move_semantics/move_semantics6.rs:25:13
|
24 | fn string_uppercase(mut data: &String) {
| - let's call the lifetime of this reference `'1`
25 | data = &data.to_uppercase();
| --------^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
| | |
| | creates a temporary value which is freed while still in use
| assignment requires that borrow lasts for `'1`
error: aborting due to 1 previous error; 1 warning emitted
I have done some chatGPTing and SOflowing(E.g. this) and I understand the following:
data.to_uppercase()
function call will create a new StringThis is clear, but what is the difference between trying to save it in data
vs newdata
. In both cases I am attempting to save this temporary value to avoid it getting dropped, but one works, and the other one doesnt.
The second example with explicit lifetimes:
fn string_uppercase<'a>(mut data: &'a String) {
// data has type &'a String
data = &data.to_uppercase();
}
data.to_uppercase()
creates a temporary variable which gets dropped at the end of the enclosing statement. This means that &data.to_uppercase()
can't have type &'a String
, it doesn't live long enough. The key fact is that the type of data
is preserved when data
is reassigned.
In the first example newdata
is a new variable and can thus have as short a lifetime as necessary. Therefore, it compiles.