Why is this temporary value dropped in a single expression?

I tried to compile the following and got a temporary which is freed while still in use error.

    let (x, y) = "1 2".split_whitespace().map(|x| x.parse::<i32>().unwrap()).collect::<Vec<_>>().split_first().unwrap();
    println!("{:?} and {:?}", x, y);

Okay, now if I split the long expression into two shorter ones, the problem is solved.

fn main() {
    let t = "1 2".split_whitespace().map(|x| x.parse::<i32>().unwrap()).collect::<Vec<_>>();
    let (x, y) = t.split_first().unwrap();
    /*
    let (x, y) = "1 2".split_whitespace().map(|x| x.parse::<i32>().unwrap()).collect::<Vec<_>>().split_first().unwrap();
     */
    println!("{:?} and {:?}", x, y);
}

Please, explain it to me, what is the difference between the two code snippets?

Values only live as long as something holds onto them. If nothing holds onto a value (i.e. when it is not bound to a variable or a pattern), it is dropped. Therefore, in the first snippet, the intermediate Vec is dropped at the end of that line. However, split_first() returns references inside the slice it is invoked on, hence you would get a dangling pointer immediately, with no backing allocation.

In the second snippet, however, you hold onto the vector to be split using the t variable, so it lives as long as the scope of t ends.

Note that in Rust, holding a reference to a value does not extend its lifetime. If you are coming from C++, you might expect there to be a special case like lifetime extension of rvalues bound to const references. This is not how it works in Rust at all – you have to make sure your references point to valid memory, otherwise the compiler will complain.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.