Skip to content

Commit b32c01b

Browse files
committed
py/compile: Fix async-for/async-with to work with simpler exc on stack.
There is now just the exception instance on the stack when an exception is raised, not the full (type, exc, traceback).
1 parent 443cc01 commit b32c01b

5 files changed

Lines changed: 33 additions & 10 deletions

File tree

py/compile.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,14 +1710,12 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
17101710
EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);
17111711
EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
17121712
EMIT_ARG(pop_jump_if, false, try_finally_label);
1713-
EMIT(pop_top);
1714-
EMIT(pop_top);
1715-
EMIT(pop_top);
1713+
EMIT(pop_top); // pop exception instance
17161714
EMIT(pop_except);
17171715
EMIT_ARG(jump, while_else_label);
17181716

17191717
EMIT_ARG(label_assign, try_finally_label);
1720-
EMIT_ARG(adjust_stack_size, 3);
1718+
EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
17211719
compile_decrease_except_level(comp);
17221720
EMIT(end_finally);
17231721
EMIT(end_except_handler);
@@ -1778,9 +1776,21 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
17781776

17791777
EMIT_ARG(label_assign, try_exception_label); // start of exception handler
17801778
EMIT(start_except_handler);
1781-
EMIT(rot_three);
1779+
1780+
// at this point the stack contains: ..., __aexit__, self, exc
1781+
EMIT(dup_top);
1782+
#if MICROPY_CPYTHON_COMPAT
1783+
EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc)
1784+
#else
1785+
compile_load_id(comp, MP_QSTR_type);
1786+
EMIT(rot_two);
1787+
EMIT_ARG(call_function, 1, 0, 0); // get type(exc)
1788+
#endif
17821789
EMIT(rot_two);
1790+
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value
1791+
// at this point the stack contains: ..., __aexit__, self, type(exc), exc, None
17831792
EMIT_ARG(call_method, 3, 0, 0);
1793+
17841794
compile_yield_from(comp);
17851795
EMIT_ARG(pop_jump_if, true, no_reraise_label);
17861796
EMIT_ARG(raise_varargs, 0);
@@ -1789,7 +1799,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
17891799
EMIT(pop_except);
17901800
EMIT_ARG(jump, end_label);
17911801

1792-
EMIT_ARG(adjust_stack_size, 5);
1802+
EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc
17931803
compile_decrease_except_level(comp);
17941804
EMIT(end_finally);
17951805
EMIT(end_except_handler);

tests/basics/async_with.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class AContext:
44
async def __aenter__(self):
55
print('enter')
66
async def __aexit__(self, exc_type, exc, tb):
7-
print('exit')
7+
print('exit', exc_type, exc)
88

99
async def f():
1010
async with AContext():
@@ -15,3 +15,13 @@ async def f():
1515
o.send(None)
1616
except StopIteration:
1717
print('finished')
18+
19+
async def g():
20+
async with AContext():
21+
raise ValueError('error')
22+
23+
o = g()
24+
try:
25+
o.send(None)
26+
except ValueError:
27+
print('ValueError')

tests/basics/async_with.py.exp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
enter
22
body
3-
exit
3+
exit None None
44
finished
5+
enter
6+
exit <class 'ValueError'> error
7+
ValueError

tests/basics/async_with2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ async def __aenter__(self):
2020
print('enter')
2121
print('f returned:', await f(10))
2222
async def __aexit__(self, exc_type, exc, tb):
23-
print('exit')
23+
print('exit', exc_type, exc)
2424
print('f returned:', await f(20))
2525

2626
async def coro():

tests/basics/async_with2.py.exp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ coro yielded: 31
99
coro yielded: 32
1010
body f returned: 33
1111
body end
12-
exit
12+
exit None None
1313
f start: 20
1414
coro yielded: 21
1515
coro yielded: 22

0 commit comments

Comments
 (0)