Python: fix match-statement parse desync that corrupts trees over RPC#8330
Open
shanman190 wants to merge 2 commits into
Open
Python: fix match-statement parse desync that corrupts trees over RPC#8330shanman190 wants to merge 2 commits into
shanman190 wants to merge 2 commits into
Conversation
Two spots in the match-case parser left source unconsumed, drifting the cursor so every later node parsed against misaligned text and came out with None children. RpcSendQueue then crashes at `el.element._id` on the None child, failing the tree transfer (handle_get_object returns a degenerate [END_OF_OBJECT]). match/case is 3.10+ and absent from older corpora, so the defect only surfaced on modernized code. - Guards on value/capture patterns: the guard source (`if <cond>`) was consumed only when the pattern wrapped as py.MatchCase. Value and capture patterns are returned bare, so the guard text stayed in the buffer. Consume it unconditionally and wrap the bare pattern in py.MatchCase(VALUE/CAPTURE) so the guard has a home; the existing py.MatchCase codec (Python and Java) and printer already handle these kinds. - Parenthesized GROUP as a class keyword value (`case Foo(k=(A() | B())):`): keyword patterns used __convert, which doesn't consume parens, while positional patterns used __convert_match_pattern. Use the latter for both. Verified across 20,635 files (numpy, home-assistant, ansible, botocore): 3 crashes -> 0, no regressions.
shanman190
commented
Jul 26, 2026
Co-authored-by: Shannon Pamperl <shanman190@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two spots in the Python
match-case parser left source unconsumed, drifting the source cursor so every later node parsed against misaligned text and came out withNonechildren.RpcSendQueuethen crashes atel.element._idon theNonechild, failing the tree transfer (handle_get_objectreturns a degenerate[END_OF_OBJECT]). Becausematch/caseis Python 3.10+ and absent from older codebases, the defect only surfaces on modernized code.Fixes (both in
_parser_visitor.py)case 1 if x:,case Enum.X if x:,case v if x:): the guard source (if <cond>) was consumed only when the pattern wrapped aspy.MatchCase. Value and capture patterns are returned bare, so the guard text stayed in the buffer. Consume it unconditionally and wrap the bare pattern inpy.MatchCase(VALUE/CAPTURE)so the guard has a home. The existingpy.MatchCasecodec (Python and Java) and printer already handle these kinds — no model or codec change needed.case Foo(k=(A() | B())):): keyword patterns used__convert(which does not consume parens) while positional patterns used__convert_match_pattern. Use the latter for both, consistent with positional handling.Verification
tests/rpc/test_match_guard_desync.py) cover both shapes end-to-end (parse →RpcSendQueue→RpcReceiveQueue→ print), asserting noNone-element padding and a clean round-trip.match/pattern suite green.