Open
Description
Namely, it's treated as a semicolon-less statement in a middle of the block.
// Like this:
fn main() {
{ 0 } // <- semicolon-less statement in a middle of the block
()
}
- "Semicolon-less" means that its type should unify with
()
(Do not discern between statements with and without semicolon after lowering to HIR #61753). - "In a middle of the block" means that it's not treated as trailing and its lifetime is not extended from the block outwards. That means "does not live long enough" errors like these do not happen (a minimized test case would be appreciated).
This is unusual because
- No other block construction or loop does this.
- The desugared form cannot be written in source code (it will either need a semicolon, or will be considered trailing).
Git blame says that the behavior was introduced by @Zoxc in #42265.
We cannot remove this behavior because it appears to be useful and code will break if it's removed.
We can, however, use it in other block constructions for which the block's trailing expression does not represent its result.
Block construction | Trailing expression is the result |
---|---|
if cond { ... } [else { ... }] |
Yes |
if let pat = expr { ... } [else { ... }] |
Yes |
while cond { ... } |
No |
while let pat = expr { ... } |
No |
for pat in expr { ... } |
No |
loop { ... } |
No |
[unsafe] { ... } |
Yes |
async { ... } |
??? |
try { ... } |
Yes |
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
petrochenkov commentedon Jun 20, 2019
Or, perhaps, avoid the lifetime prolonging behavior for trailing non-result expressions (aka trailing expressions in loops) somewhere at MIR lowering time.
With #61988 merged that's going to be very simple:
hir::ExprKind::Block
hir::ExprKind::Loop
eddyb commentedon Jun 23, 2019
I think all of the scoping is still controlled by
rustc::middle::region
, FWIW (that module should've been renamed whenever the contents were renamed...)oskgo commentedon Jul 4, 2024
Triage:
The current desugaring of
for
can be written usingloop
(#90352), so there should no longer be any special behavior here.I suspect that the regressions in the crater run would have been rejected by NLL, either because the originals were unsound, or because they hit NLL regressions (#62170), and those are no longer relevant with NLL being on by default. The crates I looked at were all using the 2015 edition, which would have been using Lexical Lifetimes before Rust 1.63.
I think this issue is outdated and should be closed, but I can't be 100% confident with there being no simple original repro.