for the first case, your "expected" code is not completely equivalent, but serves as a good mental model.
the difference is very subtle though.
this alone actually compiles:
let v = vec![1,2,3].iter();
but this does not:
// error[E0597]: `tmp` does not live long enough
let v = {
let tmp = vec![1,2,3];
let v = tmp.iter();
v
};
// same thing:
let v = {
let v = vec![1,2,3].iter();
v
};
// also same
let v = { vec![1,2,3].iter() };
so why a standalone
let v = vec![1,2,3].iter();
compiles ok, if you don't use v later? it has something to do with how the borrow checker works.
EDIT:
let me re-phrase this:
in let v = vec![1,2,3].iter();, v does borrow the temporary vector, but the temoporary value is dropped at the end of the whole (let) statement, or, you can say at the semicolon.
if v is later being used, then the variable v "lives beyond" the semicolon, which means when the temporary value gets dropped at the semicolon, there are still loans (borrows) that are live, so the borrow checker reports a lifetime error in the original snippet.
if v is never used later, then v's liveness region both starts and ends at the same semicolon (it's effectively empty), thus when the temoporary value is dropped, there's no live loans, so it passes the borrow checker.
on the other hand, if you add an inner scope, let v = { vec![1,2.3].iter() };, the temporary value is dropped at the end of the scope, i.e. the closing curly brace }, NOT the semicolon, while the variable v lives until (at least) the semicolon, which needs to extend the lifetime of the borrow to the semicolon, (even if v is never used later). so the borrow checker reports a "temporary value dropped (at the closing curly brace) while being borrowed (until the semicolon)" violation.
END of EDIT
what actually works:
use Vec::into_iter(), which moves the Vec as opposed to borrows it.
let v = vec![1,2,3].into_iter();
dbg!(v.sum::<i32>());
for this particular example where the data is constant, using an array also works, thanks to static promotion:
Here the Vec lives until the end of this statement, i.e. until ";". v is created during the statement and can only be used from the moment it is created until the end of the statement, i.e. for a very short time.
Here the tmp lives until the end of the block, i.e. until "}". The outer v is created after the block ends, so this is invalid.
This works due to a special rule, "static promotion". Since "6" is a compile time constant, it is promoted to a static value, and &6 is &'static i32.
The temporary scope of an expression is the scope that is used for the temporary variable that holds the result of that expression when used in a place context, unless it is promoted.
In a way, this seems to reduce to the simple case of a temporary, just easier to see with desugaring of the method call expression imho.
In the case of f(&5) where a value 5 is used in the place context given by the &.B But the temporary in this case it will be promoted.
So it de-sugars to static five: i32 = 5; as others seem to point out?
Whereas in the case I wrote first, it is not promoted, and so it drops at the poins you wrote.