Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for loop desugaring treats the loop's trailing expression in unusual way #61902

Open
petrochenkov opened this issue Jun 16, 2019 · 3 comments
Open
Labels
C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@petrochenkov
Copy link
Contributor

petrochenkov commented Jun 16, 2019

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

    ()
}

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
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Jun 16, 2019
@petrochenkov
Copy link
Contributor Author

We can, however, use it in other block constructions for which the block's trailing expression does not represent its result.

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:

Block construction Trailing expression is the result
hir::ExprKind::Block Yes
hir::ExprKind::Loop No

@eddyb
Copy link
Member

eddyb commented Jun 23, 2019

Or, perhaps, avoid the lifetime prolonging behavior for trailing non-result expressions (aka trailing expressions in loops) somewhere at MIR lowering time.

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
Copy link
Contributor

oskgo commented Jul 4, 2024

Triage:

The current desugaring of for can be written using loop (#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants