Back when I was first learning rust, I filed this issue with the book. In short:
while let Ok(job) = receiver.lock().unwrap().recv() {
// do something time-consuming with job
}
looks nice, but if we want to not hold the lock during the body of the while
, we need to instead write:
loop {
let job = receiver.lock().unwrap().recv().unwrap();
…
}
I now understand that the temporary values in the expression which is bound by while let
are scoped to the end of the subsequent block. That is, in
while let PAT = EXPR { … }
all the values in EXPR
live until the closing brace.
I've read Expressions - The Rust Reference
When a temporary value expression is being created that is assigned into a let declaration, however, the temporary is created with the lifetime of the enclosing block instead, as using the enclosing let declaration would be a guaranteed error (since a pointer to the temporary would be stored into a variable, but the temporary would be freed before the variable could be used). The compiler uses simple syntactic rules to decide which values are being assigned into a let binding, and therefore deserve a longer temporary lifetime.
But I don't understand. In the loop
version, if the temporaries (notably the guard) in
let job = receiver.lock().unwrap().recv().unwrap();
can be dropped as soon as the statement ends, yet allow job
to be accessed afterwards, it seems like in the context of
while let Ok(job) = receiver.lock().unwrap().recv() {
the temporaries (and guard) could be dropped before entering the block.
What am I missing here?
P. S. I understand that according to the predicate pattern loops docs
while let PAT = EXPR {
/* loop body */
}
is equivalent to
loop {
match EXPR {
PAT => { /* loop body */ },
_ => break,
}
}
but my question remains. It seems like temporaries involved in EXPR
, but not owned by bindings in PAT
could be dropped before /* loop body */
.