-
Couldn't load subscription status.
- Fork 13.9k
Stabilize if let guards (feature(if_let_guard))
#141295
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
base: master
Are you sure you want to change the base?
Conversation
|
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
|
Some changes occurred to the CTFE machinery Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred in compiler/rustc_codegen_ssa |
6fe74d9 to
5ee8970
Compare
|
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
eb0e4b4 to
0358002
Compare
This comment has been minimized.
This comment has been minimized.
92a5204 to
ab138ce
Compare
This comment has been minimized.
This comment has been minimized.
5ceca48 to
a20c4f6
Compare
This comment has been minimized.
This comment has been minimized.
1dd9974 to
5796073
Compare
|
cc @Nadrieril |
|
This needs a fcp so I'd like to roll this to someone more familiar with this feature |
|
r? @est31 |
|
I tested this with regular let chains (outside of if-let guards) and observed the same behavior - if let x = LoudDrop("0")
&& let y = pin!(LoudDrop("1"))
{}This suggests the issue might be related to let chains in general, or specifically to the interaction between let chains and "super let". If I recall correctly, super let was implemented after let chains were stabilized, which could explain this interaction |
|
I did some additional testing and found that the drop order follows a predictable pattern (though this doesn't change the fact that if let x = LoudDrop("0")
&& let y = pin!(LoudDrop("1"))
&& let z = pin!(LoudDrop("2"))
&& let w = LoudDrop("3")
{}
// 3
// 0
// 2
// 1The pattern appears to be: drops occur from bottom to top, but any pinned values are moved to the end of the drop queue |
|
I've filed this as #145328 |
add a scope for `if let` guard temporaries and bindings This fixes my concern with `if let` guard drop order, namely that the guard's bindings and temporaries were being dropped after their arm's pattern's bindings, instead of before (rust-lang/rust#141295 (comment)). The guard's bindings and temporaries now live in a new scope, which extends until (but not past) the end of the arm, guaranteeing they're dropped before the arm's pattern's bindings. This only introduces a new scope for match arms with guards. Perf results (rust-lang/rust#143376 (comment)) seemed to indicate there wasn't a significant hit to introduce a new scope on all match arms, but guard patterns (rust-lang/rust#129967) will likely benefit from only adding new scopes when necessary (with some patterns requiring multiple nested scopes). Tracking issue for `if_let_guard`: rust-lang/rust#51114 Tests are adapted from examples by `@traviscross,` `@est31,` and myself on rust-lang/rust#141295.
add a scope for `if let` guard temporaries and bindings This fixes my concern with `if let` guard drop order, namely that the guard's bindings and temporaries were being dropped after their arm's pattern's bindings, instead of before (rust-lang/rust#141295 (comment)). The guard's bindings and temporaries now live in a new scope, which extends until (but not past) the end of the arm, guaranteeing they're dropped before the arm's pattern's bindings. This only introduces a new scope for match arms with guards. Perf results (rust-lang/rust#143376 (comment)) seemed to indicate there wasn't a significant hit to introduce a new scope on all match arms, but guard patterns (rust-lang/rust#129967) will likely benefit from only adding new scopes when necessary (with some patterns requiring multiple nested scopes). Tracking issue for `if_let_guard`: rust-lang/rust#51114 Tests are adapted from examples by `@traviscross,` `@est31,` and myself on rust-lang/rust#141295.
add a scope for `if let` guard temporaries and bindings This fixes my concern with `if let` guard drop order, namely that the guard's bindings and temporaries were being dropped after their arm's pattern's bindings, instead of before (rust-lang/rust#141295 (comment)). The guard's bindings and temporaries now live in a new scope, which extends until (but not past) the end of the arm, guaranteeing they're dropped before the arm's pattern's bindings. This only introduces a new scope for match arms with guards. Perf results (rust-lang/rust#143376 (comment)) seemed to indicate there wasn't a significant hit to introduce a new scope on all match arms, but guard patterns (rust-lang/rust#129967) will likely benefit from only adding new scopes when necessary (with some patterns requiring multiple nested scopes). Tracking issue for `if_let_guard`: rust-lang/rust#51114 Tests are adapted from examples by `@traviscross,` `@est31,` and myself on rust-lang/rust#141295.
add a scope for `if let` guard temporaries and bindings This fixes my concern with `if let` guard drop order, namely that the guard's bindings and temporaries were being dropped after their arm's pattern's bindings, instead of before (rust-lang/rust#141295 (comment)). The guard's bindings and temporaries now live in a new scope, which extends until (but not past) the end of the arm, guaranteeing they're dropped before the arm's pattern's bindings. This only introduces a new scope for match arms with guards. Perf results (rust-lang/rust#143376 (comment)) seemed to indicate there wasn't a significant hit to introduce a new scope on all match arms, but guard patterns (rust-lang/rust#129967) will likely benefit from only adding new scopes when necessary (with some patterns requiring multiple nested scopes). Tracking issue for `if_let_guard`: rust-lang/rust#51114 Tests are adapted from examples by `@traviscross,` `@est31,` and myself on rust-lang/rust#141295.
add a scope for `if let` guard temporaries and bindings This fixes my concern with `if let` guard drop order, namely that the guard's bindings and temporaries were being dropped after their arm's pattern's bindings, instead of before (rust-lang/rust#141295 (comment)). The guard's bindings and temporaries now live in a new scope, which extends until (but not past) the end of the arm, guaranteeing they're dropped before the arm's pattern's bindings. This only introduces a new scope for match arms with guards. Perf results (rust-lang/rust#143376 (comment)) seemed to indicate there wasn't a significant hit to introduce a new scope on all match arms, but guard patterns (rust-lang/rust#129967) will likely benefit from only adding new scopes when necessary (with some patterns requiring multiple nested scopes). Tracking issue for `if_let_guard`: rust-lang/rust#51114 Tests are adapted from examples by `@traviscross,` `@est31,` and myself on rust-lang/rust#141295.
|
Hi everyone, It’s been a while since my last update - quite a lot has happened in the meantime, but the main thing is I'm still here I’ve noticed that many fixes, including the main concern, have already been merged - big thanks to @dianne for the help, and to @theemathas for spotting some interesting edge cases Also, the documentation (thanks again to dianne) has been created and marked as waiting-on-stabilization. Am I right in assuming that means it’s in good shape? So from what I see, the major concerns like the drop order bug and the docs are resolved I just wanted to check with the team: are there any other blockers before I start extending the test suite and working through the conflicts? |
|
Thanks for checking in and following up on this. Looking back over the issue, I agree that the primary blockers here have been resolved. I would indeed suggest extending the tests and rebasing the branch. We haven't yet approved the Reference PR (rust-lang/reference#1957), and that will need to happen before we merge this PR, but on a skim, it looks to be in good shape; this won't hold things up unduly. We'll probably want to see the extended tests before approving this anyway, so as to compare the behavior with what we're documenting. If you could leave a note here when the tests are extended and the branch is rebased, I'll plan to have a look, resolve the concern I had filed, restart the proposed FCP, and finish reviewing the Reference PR. |
bde3195 to
902b4d2
Compare
|
This PR modifies |
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This comment has been minimized.
This comment has been minimized.
902b4d2 to
54371e6
Compare
This comment has been minimized.
This comment has been minimized.
54371e6 to
725c559
Compare
|
The Miri subtree was changed cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
725c559 to
5650d71
Compare
This comment has been minimized.
This comment has been minimized.
5650d71 to
3a6c8c8
Compare
|
Conflicts are resolved For test part from what I see is dianne added a test for drop order which is covering the drop order fix, I updated description and specify 3 new tests in there (one of them I adopted from here #141295 (comment)) And as for tests for this and this I will add them later on if noone else will do this before, and point them in unresolved issues as non blocking |
|
☔ The latest upstream changes (presumably #148049) made this pull request unmergeable. Please resolve the merge conflicts. |
Summary
This proposes the stabilization of
if letguards (tracking issue: #51114, RFC: rust-lang/rfcs#2294). This feature allowsif letexpressions to be used directly within match arm guards, enabling conditional pattern matching within guard clauses.What is being stabilized
The ability to use
if letexpressions within match arm guards.Example:
Motivation
The primary motivation for
if letguards is to reduce nesting and improve readability when conditional logic depends on pattern matching. Without this feature, such logic requires nestedif letstatements within match arms:Implementation and Testing
The feature has been implemented and tested comprehensively across different scenarios:
Core Functionality Tests
Scoping and variable binding:
scope.rs- Verifies that bindings created inif letguards are properly scoped and available in match armsshadowing.rs- Tests that variable shadowing works correctly within guardsscoping-consistency.rs- Ensures temporaries in guards remain valid for the duration of their match armsType system integration:
type-inference.rs- Confirms type inference works correctly inif letguardstypeck.rs- Verifies type mismatches are caught appropriatelyPattern matching semantics:
exhaustive.rs- Validates thatif letguards are correctly handled in exhaustiveness analysismove-guard-if-let.rsandmove-guard-if-let-chain.rs- Test that conditional moves in guards are tracked correctly by the borrow checkerError Handling and Diagnostics
warns.rs- Tests warnings for irrefutable patterns and unreachable code in guardsparens.rs- Ensures parentheses aroundletexpressions are properly rejectedmacro-expanded.rs- Verifies macro expansions that produce invalid constructs are caughtguard-mutability-2.rs- Tests mutability and ownership violations in guardsast-validate-guards.rs- Validates AST-level syntax restrictionsDrop Order and Temporaries
Key insight: Unlike
let_chainsin regularifexpressions,if letguards do not have drop order inconsistencies because:drop-order.rs- Check drop order of temporaries create in match guardscompare-drop-order.rs- Compares drop order betweenif letguards and nestedif letin match arms, confirming they behave identically across all editionslet chainwas made by @est31drop-order-comparisons-let-chains.rs- Compares drop order betweenlet chainsinif let guardand regularifexpressionsif-let-guards.rs- Test correctness of drop order for bindings and temporariesif-let-guards-2- The same test as above but more comprehensive and tests more interactions between different features and their drop order, checking that drop order is correct, created by @traviscrossEdition Compatibility
This feature stabilizes on all editions, unlike
let chainswhich was limited to edition 2024. This is safe because:if letguards don't suffer from the drop order issues that affectedlet chainsin regularifexpressionsInteractions with Future Features
The lang team has reviewed potential interactions with planned "guard patterns" and determined that stabilizing
if letguards now does not create obstacles for future work. The scoping and evaluation semantics established here align with what guard patterns will need.Unresolved Issues
let chainsinsideif letguard is the sameif letguard temporaries and bindings #143376if letguards with updated scoping rules reference#1957)Related:
if letguards with updated scoping rules reference#1957