i was working on a neural network library to find that you can take reference of a clone-d temporary value:
fn main() {
let v = vec![String::from("hello"),String::from("world")];
let r: &Vec<_> = &v.clone();
println!("{:?}",r);
}
if i understand ownership correctly, the call to clone returns a temporary value, whose reference i store in a variable. after that, the temporary value gets dropped, which makes my reference invalid. so this should not compile, but it does. why is that?
In some cases, ie when you take a reference to a temporary and assign it to a variable, the compiler does temporary lifetime extension. So the temporary lives for the whole scope rather than the statement. This only happens for a direct reference being immediately assigned to a let binding. If you did like &v.clone()[0] then the temporary clone will not get lifetime extended and you should get an error
I don't think that's entirely true (anymore?). That code compiles and works fine with &v.clone()[0] or &(v.clone()[0]). Also if v is an array instead of a vector. I guess there's some wizardry in Vec (and slices) to make the compiler understand how to shrink down ownership. I had to resort to a different collection type access the element using iter().next() to finally see the expected error pop up (I switched to a different collection type for no reason here):
use std::collections::BTreeSet;
fn main() {
let mut v = BTreeSet::new();
v.insert(String::from("hello"));
v.insert(String::from("world"));
let r = &(v.clone().iter().next());
println!("{:?}", r);
}
Compiling playground v0.0.1 (/playground)
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:7:15
|
7 | let r = &(v.clone().iter().next());
| ^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
8 | println!("{:?}", r);
| - borrow later used here
|
= note: consider using a `let` binding to create a longer lived value