Commit 7b0abac
committed
[mypyc] Fix AttributeError in async try/finally with mixed return paths
Async functions with try/finally blocks were raising AttributeError when:
- Some paths in the try block return while others don't
- The non-return path is executed at runtime
- No further await calls are needed
This occurred because mypyc's IR requires all control flow paths to assign
to spill targets (temporary variables stored as generator attributes). The
non-return path assigns NULL to maintain this invariant, but reading NULL
attributes raises AttributeError in Python.
Created a new IR operation `GetAttrNullable` that can read NULL attributes
without raising AttributeError. This operation is used specifically in
try/finally resolution when reading spill targets.
- Added `GetAttrNullable` class to mypyc/ir/ops.py with error_kind=ERR_NEVER
- Added `read_nullable_attr` method to IRBuilder for creating these operations
- Modified `try_finally_resolve_control` in statement.py to use GetAttrNullable
only for spill targets (attributes starting with '__mypyc_temp__')
- Implemented C code generation in emitfunc.py that reads attributes without
NULL checks and only increments reference count if not NULL
- Added visitor implementations to all required files:
- ir/pprint.py (pretty printing)
- analysis/dataflow.py (dataflow analysis)
- analysis/ircheck.py (IR validation)
- analysis/selfleaks.py (self leak analysis)
- transform/ir_transform.py (IR transformation)
1. **Separate operation vs flag**: Created a new operation instead of adding
a flag to GetAttr for better performance - avoids runtime flag checks on
every attribute access.
2. **Targeted fix**: Only applied to spill targets in try/finally resolution,
not a general replacement for GetAttr. This minimizes risk and maintains
existing behavior for all other attribute access.
3. **No initialization changes**: Initially tried initializing spill targets
to Py_None instead of NULL, but this would incorrectly make try/finally
blocks return None instead of falling through to subsequent code.
Added two test cases to mypyc/test-data/run-async.test:
1. **testAsyncTryFinallyMixedReturn**: Tests the basic issue with async
try/finally blocks containing mixed return/non-return paths.
2. **testAsyncWithMixedReturn**: Tests async with statements (which use
try/finally under the hood) to ensure the fix works for this common
pattern as well.
Both tests verify that the AttributeError no longer occurs when taking
the non-return path through the try block.
See mypyc/mypyc#11151 parent 5e9d657 commit 7b0abac
File tree
10 files changed
+401
-2
lines changed- mypyc
- analysis
- codegen
- irbuild
- ir
- test-data
- transform
10 files changed
+401
-2
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| |||
209 | 210 | | |
210 | 211 | | |
211 | 212 | | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
212 | 216 | | |
213 | 217 | | |
214 | 218 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
319 | 320 | | |
320 | 321 | | |
321 | 322 | | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
322 | 327 | | |
323 | 328 | | |
324 | 329 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
114 | 115 | | |
115 | 116 | | |
116 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
117 | 125 | | |
118 | 126 | | |
119 | 127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
426 | 427 | | |
427 | 428 | | |
428 | 429 | | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
429 | 448 | | |
430 | 449 | | |
431 | 450 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
799 | 799 | | |
800 | 800 | | |
801 | 801 | | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
802 | 831 | | |
803 | 832 | | |
804 | 833 | | |
| |||
1728 | 1757 | | |
1729 | 1758 | | |
1730 | 1759 | | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
1731 | 1764 | | |
1732 | 1765 | | |
1733 | 1766 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
128 | 129 | | |
129 | 130 | | |
130 | 131 | | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
131 | 135 | | |
132 | 136 | | |
133 | 137 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| 75 | + | |
75 | 76 | | |
76 | 77 | | |
77 | 78 | | |
| |||
708 | 709 | | |
709 | 710 | | |
710 | 711 | | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
711 | 721 | | |
712 | 722 | | |
713 | 723 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
| |||
653 | 654 | | |
654 | 655 | | |
655 | 656 | | |
656 | | - | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
657 | 663 | | |
658 | 664 | | |
659 | | - | |
| 665 | + | |
660 | 666 | | |
661 | 667 | | |
662 | 668 | | |
| |||
0 commit comments