Danilo Souza Morães
Danilo Souza Morães

Reputation: 1593

Why can I call iter and collect inline without lifetime issues?

Why can I run the following statement without issues?

println!("{:?}", (vec!["1".to_string(), "1".to_string(), "1".to_string()]).iter().collect::<Vec<&String>>());

If I understood it correctly, it creates an array of owned Strings, get's an iterator of String references and then collects an array of String references. But these references refer to an array that ceased existing in the beginning of that statement. Why does it work?

Upvotes: 2

Views: 59

Answers (1)

prog-fh
prog-fh

Reputation: 16925

The lifetime is extended till the end of the statement (i.e. the semicolon), not at the end of .iter().

The compiler explains this when you split this code into two statements.

In the Rust Reference we find this:

Apart from lifetime extension, the temporary scope of an expression is the smallest scope that contains the expression and is one of the following:

  • The entire function body.
  • A statement.
  • The body of an if, while or loop expression.
  • The else block of an if expression.
  • The condition expression of an if or while expression, or a match guard.
  • The expression for a match arm.
  • The second operand of a lazy boolean expression.

In this case, the smallest scope is the statement.

fn main() {
    let v = (vec!["1".to_string(), "1".to_string(), "1".to_string()])
        .iter()
        .collect::<Vec<&String>>(); // !!! ERROR
    println!("{:?}", v);
}
...
4 |         .collect::<Vec<&String>>();
  |                                   - temporary value is freed at the end of this statement
...

Upvotes: 7

Related Questions