Skip to content

de-duplicate condition scoping logic between AST→HIR lowering and ScopeTree construction #143213

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

dianne
Copy link
Contributor

@dianne dianne commented Jun 29, 2025

There was some overlap between rustc_ast_lowering::LoweringContext::lower_cond and rustc_hir_analysis::check::region::resolve_expr, so I've removed the former and migrated its logic to the latter, with some simplifications.

Consequences:

  • For while and if expressions' let-chains, this changes the HirIds for the &&s to properly correspond to their AST nodes. This is how guards were handled already.
  • This makes match guards share previously-duplicated logic with if/while expressions. This will also be used by guard pattern1 guards.
  • Aside from legacy syntax extensions (e.g. some builtin macros) that directly feed AST to the compiler, it's currently impossible to put attributes directly on && operators in let chains2. Nonetheless, attributes on && operators in let chains in if/while expression conditions are no longer silently ignored and will be lowered.
  • This no longer wraps conditions in DropTemps, so the HIR and THIR will be slightly smaller.
  • DesugaringKind::CondTemporary is now gone. It's no longer applied to any spans, and all uses of it were dead since they were made to account for if and while being desugared to match on a boolean scrutinee.
  • Should be a marginal perf improvement beyond that due to leveraging ScopeTree construction's clever handling of && and ||:
    • This removes some unnecessary terminating scopes that were placed around top-level && and || operators in conditions. When lowered to MIR, logical operator chains don't create intermediate boolean temporaries, so there's no temporary to drop. The linked snippet handles wrapping the operands in terminating scopes as necessary, in case they create temporaries.
    • The linked snippet takes care of letting let temporaries live and terminating other operands, so we don't need separate traversals of && chains for that.

Footnotes

  1. Tracking issue for RFC 3637: Guard patterns #129967

  2. Case-by-case, here's my justification: #[attr] e1 && e2 applies the attribute to e1. In #[attr] (e1 && e2) , the attribute is on the parentheses in the AST, plus it'd fail to parse if e1 or e2 contains a let. In #[attr] expands_to_let_chain!(), the attribute would already be ignored (How to treat inert attributes on macro invocations? #63221) and it'd fail to parse anyway; even if the expansion site is a condition, the expansion wouldn't be parsed with Restrictions::ALLOW_LET. If it was allowed, the notion of a "reparse context" from https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449 would be necessary in order to make let-chains left-associative; multiple places in the compiler assume they are.

@rustbot
Copy link
Collaborator

rustbot commented Jun 29, 2025

r? @WaffleLapkin

rustbot has assigned @WaffleLapkin.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 29, 2025
@rust-log-analyzer

This comment has been minimized.

@dianne

This comment was marked as resolved.

@dianne dianne force-pushed the lower-cond-tweaks branch from 686da48 to 13c796b Compare June 29, 2025 22:25
@rustbot
Copy link
Collaborator

rustbot commented Jun 29, 2025

Some changes occurred in coverage tests.

cc @Zalathar

@dianne dianne force-pushed the lower-cond-tweaks branch from 13c796b to be191a0 Compare June 29, 2025 23:13
@dianne
Copy link
Contributor Author

dianne commented Jun 29, 2025

actually, I've convinced myself it's cleanest to get rid of lower_cond, so I've done that (diff of diffs). the coverage tests' maps are now back to normal. instead, I had to change a diagnostic and a handful of things in clippy that assumed if expressions have DropTemps in them. sorry for the noise! this ended up being more disruptive than intended. to keep keep the scope of this change as small as possible, I've tried to leave lints' behaviors untouched. without the extra meddling this does to avoid linting on let chains,

  • clippy::needless_if would lint on if let x = () {}
  • clippy::while_immutable_condition would lint on while let x = () {}
  • clippy::needless_bool would lint on if let x = () && true {}

edit: I just noticed that I've left DesugaringKind::CondTemporary unused. I'll have to clean that up. it looks like it was checked in some diagnostics, but when I tested locally at least I don't think I got any UI test failures, so I'll look closer into if anything changed.

@rustbot author

@rustbot
Copy link
Collaborator

rustbot commented Jun 30, 2025

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 30, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jun 30, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@dianne
Copy link
Contributor Author

dianne commented Jun 30, 2025

alright, I've removed DesugaringKind::CondTemporary. it looks like all uses of it were out-of-date.

  • there was a use in checking the types of literal patterns to account for if and while being desugared as match expressions on booleans. this is not the case anymore, so the DesugaringKind check was dead.
  • there was a use in warn_if_unreachable, which also seems to have been accounting for desugaring if and while to match. now that if is its own thing in the HIR, the unreachability warning in check_expr_if uses the success block's span, so the DesugaringKind check was dead.
  • the doc comment on the DesugaringKind::CondTemporary variant was also out-of-date, again referring to desugaring if and while to match

all of this predates me contributing to the compiler, but I guess putting DropTemps in the conditions for if and while was a holdover from when it was necessary because they desugared to match?

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants