Guard patterns: MIR lowering#154545
Conversation
|
Some changes occurred in match lowering cc @Nadrieril |
This comment has been minimized.
This comment has been minimized.
9a8cf61 to
1d0134e
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Guard patterns: MIR lowering
| let mut guards = sub_branch.guard_patterns; | ||
| if let Some(guard) = arm.guard { | ||
| guards.push(guard); | ||
| }; | ||
|
|
||
| if guards.is_empty() { | ||
| self.bind_matched_candidate_for_arm_body( | ||
| block, | ||
| schedule_drops, | ||
| sub_branch.bindings.iter(), | ||
| ); | ||
|
|
||
| return block | ||
| }; |
There was a problem hiding this comment.
It's very awkward that this duplicates the else block below.
There should be a way to rephrase the if condition so that it only fires if there is at least one guard in the arm and/or guard patterns.
There was a problem hiding this comment.
Agree. It's just a workaround untill I figure out smth better
There was a problem hiding this comment.
It'd be nice for guards from match arms and guards from guard patterns to be handled the same here. Could the arm's guard not be part of the PatternExtraData along with the guards from patterns, so they can be handled uniformly?
Also, anything with a guard, whether it's from a match arm or a guard pattern, will need some equivalent of the match_scope there; returning to that scope after guard execution is what drops the guard's temporaries.
1d0134e to
d3deeac
Compare
|
@Zalathar could you schedule perf run once again? |
|
It’ll be faster to just let the old try job keep running. The new changes shouldn’t affect perf, so I think benchmarking the current job will be fine. |
There was a problem hiding this comment.
This will need some //@ run-pass tests to make sure the runtime semantics are correct, possibly also with //@ compile-flags: -Zvalidate-mir -Zlint-mir to help catch drop scheduling bugs. Getting scoping right and scheduling drops properly for guard patterns in all cases is a little subtle and will end up being the trickiest part of this; I know my first stab at that produced broken MIR ^^
You'll also want to look into how fake borrows work; patterns with guards on them will need fake borrows to make sure the guards can't modify any places being tested. For match and irrefutable let, this is needed for soundness (and in other cases, we should probably be consistent with that). At a glance, it doesn't look like this is setting has_guard for candidates, so certain things like fake borrows won't work. Likewise, this will need tests. I think some other things might use has_guard too, like or-pattern simplification.
As a meta note, I do have some opinions about how guard patterns should be implemented from my own attempt at lowering them to MIR last year. I'll try not just to compare this to what I'd do, since I'd effectively be reviewing my own code, but it might help to have more eyes on it just in case.
| let mut guards = sub_branch.guard_patterns; | ||
| if let Some(guard) = arm.guard { | ||
| guards.push(guard); | ||
| }; | ||
|
|
||
| if guards.is_empty() { | ||
| self.bind_matched_candidate_for_arm_body( | ||
| block, | ||
| schedule_drops, | ||
| sub_branch.bindings.iter(), | ||
| ); | ||
|
|
||
| return block | ||
| }; |
There was a problem hiding this comment.
It'd be nice for guards from match arms and guards from guard patterns to be handled the same here. Could the arm's guard not be part of the PatternExtraData along with the guards from patterns, so they can be handled uniformly?
Also, anything with a guard, whether it's from a match arm or a guard pattern, will need some equivalent of the match_scope there; returning to that scope after guard execution is what drops the guard's temporaries.
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (94df5ce): comparison URL. Overall result: ❌ regressions - no action neededBenchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf. @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (secondary 2.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 2.6%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 484.385s -> 484.355s (-0.01%) |
This pr (hopefully) implements THIR -> MIR lowering of guard patterns:
PatKind::Guardis encountered, we lower the subpattern and push ExprId of a condition toextra_data.guard_patternsMatchTreeSubBranchbind_ang_guard_matched_candidatewe push actual guard to thesub_branch.guard_patternsvecVec<ExprId>of guards and (hopefully) merge them in MIR chainr? @dianne
cc @Nadrieril, @max-niederman