Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 289f408

Browse files
authored
Fix match statement semantics for "or" pattern (#21156)
Fixes mypyc/mypyc#1166 Authored by Codex
1 parent 272a1ea commit 289f408

3 files changed

Lines changed: 111 additions & 56 deletions

File tree

mypyc/irbuild/match.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,25 @@ def visit_value_pattern(self, pattern: ValuePattern) -> None:
108108
self.builder.add_bool_branch(cond, self.code_block, self.next_block)
109109

110110
def visit_or_pattern(self, pattern: OrPattern) -> None:
111-
backup_block = self.next_block
112-
self.next_block = BasicBlock()
111+
code_block = self.code_block
112+
next_block = self.next_block
113113

114114
for p in pattern.patterns:
115+
self.code_block = BasicBlock()
116+
self.next_block = BasicBlock()
117+
115118
# Hack to ensure the as pattern is bound to each pattern in the
116119
# "or" pattern, but not every subpattern
117120
backup = self.as_pattern
118121
p.accept(self)
119122
self.as_pattern = backup
120123

124+
self.builder.activate_block(self.code_block)
125+
self.builder.goto(code_block)
121126
self.builder.activate_block(self.next_block)
122-
self.next_block = BasicBlock()
123127

124-
self.next_block = backup_block
128+
self.code_block = code_block
129+
self.next_block = next_block
125130
self.builder.goto(self.next_block)
126131

127132
def visit_class_pattern(self, pattern: ClassPattern) -> None:

mypyc/test-data/irbuild-match.test

Lines changed: 81 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ def f():
4848
r8, r9 :: object
4949
L0:
5050
r0 = int_eq 246, 246
51-
if r0 goto L3 else goto L1 :: bool
51+
if r0 goto L1 else goto L2 :: bool
5252
L1:
53-
r1 = int_eq 246, 912
54-
if r1 goto L3 else goto L2 :: bool
53+
goto L5
5554
L2:
56-
goto L4
55+
r1 = int_eq 246, 912
56+
if r1 goto L3 else goto L4 :: bool
5757
L3:
58+
goto L5
59+
L4:
60+
goto L6
61+
L5:
5862
r2 = 'matched'
5963
r3 = builtins :: module
6064
r4 = 'print'
@@ -63,9 +67,9 @@ L3:
6367
r7 = load_address r6
6468
r8 = PyObject_Vectorcall(r5, r7, 1, 0)
6569
keep_alive r2
66-
goto L5
67-
L4:
68-
L5:
70+
goto L7
71+
L6:
72+
L7:
6973
r9 = box(None, 1)
7074
return r9
7175

@@ -86,19 +90,27 @@ def f():
8690
r10, r11 :: object
8791
L0:
8892
r0 = int_eq 2, 2
89-
if r0 goto L5 else goto L1 :: bool
93+
if r0 goto L1 else goto L2 :: bool
9094
L1:
91-
r1 = int_eq 2, 4
92-
if r1 goto L5 else goto L2 :: bool
95+
goto L9
9396
L2:
94-
r2 = int_eq 2, 6
95-
if r2 goto L5 else goto L3 :: bool
97+
r1 = int_eq 2, 4
98+
if r1 goto L3 else goto L4 :: bool
9699
L3:
97-
r3 = int_eq 2, 8
98-
if r3 goto L5 else goto L4 :: bool
100+
goto L9
99101
L4:
100-
goto L6
102+
r2 = int_eq 2, 6
103+
if r2 goto L5 else goto L6 :: bool
101104
L5:
105+
goto L9
106+
L6:
107+
r3 = int_eq 2, 8
108+
if r3 goto L7 else goto L8 :: bool
109+
L7:
110+
goto L9
111+
L8:
112+
goto L10
113+
L9:
102114
r4 = 'matched'
103115
r5 = builtins :: module
104116
r6 = 'print'
@@ -107,9 +119,9 @@ L5:
107119
r9 = load_address r8
108120
r10 = PyObject_Vectorcall(r7, r9, 1, 0)
109121
keep_alive r4
110-
goto L7
111-
L6:
112-
L7:
122+
goto L11
123+
L10:
124+
L11:
113125
r11 = box(None, 1)
114126
return r11
115127

@@ -280,16 +292,20 @@ L1:
280292
r6 = load_address r5
281293
r7 = PyObject_Vectorcall(r4, r6, 1, 0)
282294
keep_alive r1
283-
goto L9
295+
goto L11
284296
L2:
285297
r8 = int_eq 246, 4
286-
if r8 goto L5 else goto L3 :: bool
298+
if r8 goto L3 else goto L4 :: bool
287299
L3:
288-
r9 = int_eq 246, 6
289-
if r9 goto L5 else goto L4 :: bool
300+
goto L7
290301
L4:
291-
goto L6
302+
r9 = int_eq 246, 6
303+
if r9 goto L5 else goto L6 :: bool
292304
L5:
305+
goto L7
306+
L6:
307+
goto L8
308+
L7:
293309
r10 = 'here 2 | 3'
294310
r11 = builtins :: module
295311
r12 = 'print'
@@ -298,11 +314,11 @@ L5:
298314
r15 = load_address r14
299315
r16 = PyObject_Vectorcall(r13, r15, 1, 0)
300316
keep_alive r10
301-
goto L9
302-
L6:
317+
goto L11
318+
L8:
303319
r17 = int_eq 246, 246
304-
if r17 goto L7 else goto L8 :: bool
305-
L7:
320+
if r17 goto L9 else goto L10 :: bool
321+
L9:
306322
r18 = 'here 123'
307323
r19 = builtins :: module
308324
r20 = 'print'
@@ -311,9 +327,9 @@ L7:
311327
r23 = load_address r22
312328
r24 = PyObject_Vectorcall(r21, r23, 1, 0)
313329
keep_alive r18
314-
goto L9
315-
L8:
316-
L9:
330+
goto L11
331+
L10:
332+
L11:
317333
r25 = box(None, 1)
318334
return r25
319335

@@ -456,15 +472,19 @@ def f():
456472
r10, r11 :: object
457473
L0:
458474
r0 = int_eq 2, 2
459-
if r0 goto L3 else goto L1 :: bool
475+
if r0 goto L1 else goto L2 :: bool
460476
L1:
477+
goto L5
478+
L2:
461479
r1 = load_address PyLong_Type
462480
r2 = object 1
463481
r3 = CPy_TypeCheck(r2, r1)
464-
if r3 goto L3 else goto L2 :: bool
465-
L2:
466-
goto L4
482+
if r3 goto L3 else goto L4 :: bool
467483
L3:
484+
goto L5
485+
L4:
486+
goto L6
487+
L5:
468488
r4 = 'matched'
469489
r5 = builtins :: module
470490
r6 = 'print'
@@ -473,9 +493,9 @@ L3:
473493
r9 = load_address r8
474494
r10 = PyObject_Vectorcall(r7, r9, 1, 0)
475495
keep_alive r4
476-
goto L5
477-
L4:
478-
L5:
496+
goto L7
497+
L6:
498+
L7:
479499
r11 = box(None, 1)
480500
return r11
481501

@@ -532,25 +552,29 @@ L0:
532552
r0 = int_eq 2, 2
533553
r1 = object 1
534554
x = r1
535-
if r0 goto L3 else goto L1 :: bool
555+
if r0 goto L1 else goto L2 :: bool
536556
L1:
557+
goto L5
558+
L2:
537559
r2 = int_eq 2, 4
538560
r3 = object 2
539561
x = r3
540-
if r2 goto L3 else goto L2 :: bool
541-
L2:
542-
goto L4
562+
if r2 goto L3 else goto L4 :: bool
543563
L3:
564+
goto L5
565+
L4:
566+
goto L6
567+
L5:
544568
r4 = builtins :: module
545569
r5 = 'print'
546570
r6 = CPyObject_GetAttr(r4, r5)
547571
r7 = [x]
548572
r8 = load_address r7
549573
r9 = PyObject_Vectorcall(r6, r8, 1, 0)
550574
keep_alive x
551-
goto L5
552-
L4:
553-
L5:
575+
goto L7
576+
L6:
577+
L7:
554578
r10 = box(None, 1)
555579
return r10
556580

@@ -809,7 +833,7 @@ L0:
809833
r1 = PyObject_IsInstance(x, r0)
810834
r2 = r1 >= 0 :: signed
811835
r3 = truncate r1: i32 to builtins.bool
812-
if r3 goto L1 else goto L5 :: bool
836+
if r3 goto L1 else goto L7 :: bool
813837
L1:
814838
r4 = 'num'
815839
r5 = CPyObject_GetAttr(x, r4)
@@ -818,17 +842,21 @@ L1:
818842
r8 = PyObject_IsTrue(r7)
819843
r9 = r8 >= 0 :: signed
820844
r10 = truncate r8: i32 to builtins.bool
821-
if r10 goto L4 else goto L2 :: bool
845+
if r10 goto L2 else goto L3 :: bool
822846
L2:
847+
goto L6
848+
L3:
823849
r11 = object 2
824850
r12 = PyObject_RichCompare(r5, r11, 2)
825851
r13 = PyObject_IsTrue(r12)
826852
r14 = r13 >= 0 :: signed
827853
r15 = truncate r13: i32 to builtins.bool
828-
if r15 goto L4 else goto L3 :: bool
829-
L3:
830-
goto L5
854+
if r15 goto L4 else goto L5 :: bool
831855
L4:
856+
goto L6
857+
L5:
858+
goto L7
859+
L6:
832860
r16 = 'matched'
833861
r17 = builtins :: module
834862
r18 = 'print'
@@ -837,11 +865,12 @@ L4:
837865
r21 = load_address r20
838866
r22 = PyObject_Vectorcall(r19, r21, 1, 0)
839867
keep_alive r16
840-
goto L6
841-
L5:
842-
L6:
868+
goto L8
869+
L7:
870+
L8:
843871
r23 = box(None, 1)
844872
return r23
873+
845874
[case testAsPatternDoesntBleedIntoSubPatterns_python3_10]
846875
class C:
847876
__match_args__ = ("a", "b")

mypyc/test-data/run-match.test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,27 @@ test 21 ('')
230230
test 21 (' as well')
231231
test sequence final
232232
test final
233+
234+
[case testMatchOrSequencePattern_python3_10]
235+
def f(x: tuple[str, str]) -> str:
236+
match x:
237+
case ("X", "Y") | ("X", "Z"):
238+
return "THERE"
239+
case _:
240+
return "OTHER"
241+
242+
[file driver.py]
243+
from native import f
244+
245+
print(f(("X", "Y")))
246+
print(f(("X", "Z")))
247+
print(f(("X", "A")))
248+
249+
[out]
250+
THERE
251+
THERE
252+
OTHER
253+
233254
[case testCustomMappingAndSequenceObjects_python3_10]
234255
def f(x: object) -> None:
235256
match x:

0 commit comments

Comments
 (0)