Skip to content

Commit 937cebc

Browse files
authored
bpo-44298: Fix line numbers for early exits in with statements. (GH-26513)
1 parent 4eed282 commit 937cebc

File tree

4 files changed

+3027
-2971
lines changed

4 files changed

+3027
-2971
lines changed

Lib/test/test_sys_settrace.py

+46
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,52 @@ def func():
995995
(5, 'line'),
996996
(5, 'return')])
997997

998+
def test_early_exit_with(self):
999+
1000+
class C:
1001+
def __enter__(self):
1002+
return self
1003+
def __exit__(*args):
1004+
pass
1005+
1006+
def func_break():
1007+
for i in (1,2):
1008+
with C():
1009+
break
1010+
pass
1011+
1012+
def func_return():
1013+
with C():
1014+
return
1015+
1016+
self.run_and_compare(func_break,
1017+
[(0, 'call'),
1018+
(1, 'line'),
1019+
(2, 'line'),
1020+
(-5, 'call'),
1021+
(-4, 'line'),
1022+
(-4, 'return'),
1023+
(3, 'line'),
1024+
(2, 'line'),
1025+
(-3, 'call'),
1026+
(-2, 'line'),
1027+
(-2, 'return'),
1028+
(4, 'line'),
1029+
(4, 'return')])
1030+
1031+
self.run_and_compare(func_return,
1032+
[(0, 'call'),
1033+
(1, 'line'),
1034+
(-11, 'call'),
1035+
(-10, 'line'),
1036+
(-10, 'return'),
1037+
(2, 'line'),
1038+
(1, 'line'),
1039+
(-9, 'call'),
1040+
(-8, 'line'),
1041+
(-8, 'return'),
1042+
(1, 'return')])
1043+
9981044

9991045
class SkipLineEventsTraceTestCase(TraceTestCase):
10001046
"""Repeat the trace tests, but with per-line events skipped"""

Python/compile.c

+17-7
Original file line numberDiff line numberDiff line change
@@ -1796,7 +1796,6 @@ static int
17961796
compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
17971797
int preserve_tos)
17981798
{
1799-
int loc;
18001799
switch (info->fb_type) {
18011800
case WHILE_LOOP:
18021801
case EXCEPTION_HANDLER:
@@ -1850,7 +1849,6 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
18501849

18511850
case WITH:
18521851
case ASYNC_WITH:
1853-
loc = c->u->u_lineno;
18541852
SET_LOC(c, (stmt_ty)info->fb_datum);
18551853
ADDOP(c, POP_BLOCK);
18561854
if (preserve_tos) {
@@ -1865,7 +1863,10 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
18651863
ADDOP(c, YIELD_FROM);
18661864
}
18671865
ADDOP(c, POP_TOP);
1868-
c->u->u_lineno = loc;
1866+
/* The exit block should appear to execute after the
1867+
* statement causing the unwinding, so make the unwinding
1868+
* instruction artificial */
1869+
c->u->u_lineno = -1;
18691870
return 1;
18701871

18711872
case HANDLER_CLEANUP:
@@ -3020,12 +3021,17 @@ compiler_return(struct compiler *c, stmt_ty s)
30203021
if (preserve_tos) {
30213022
VISIT(c, expr, s->v.Return.value);
30223023
} else {
3023-
/* Emit instruction with line number for expression */
3024+
/* Emit instruction with line number for return value */
30243025
if (s->v.Return.value != NULL) {
30253026
SET_LOC(c, s->v.Return.value);
30263027
ADDOP(c, NOP);
30273028
}
30283029
}
3030+
if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) {
3031+
SET_LOC(c, s);
3032+
ADDOP(c, NOP);
3033+
}
3034+
30293035
if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL))
30303036
return 0;
30313037
if (s->v.Return.value == NULL) {
@@ -3044,6 +3050,8 @@ static int
30443050
compiler_break(struct compiler *c)
30453051
{
30463052
struct fblockinfo *loop = NULL;
3053+
/* Emit instruction with line number */
3054+
ADDOP(c, NOP);
30473055
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
30483056
return 0;
30493057
}
@@ -3062,6 +3070,8 @@ static int
30623070
compiler_continue(struct compiler *c)
30633071
{
30643072
struct fblockinfo *loop = NULL;
3073+
/* Emit instruction with line number */
3074+
ADDOP(c, NOP);
30653075
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
30663076
return 0;
30673077
}
@@ -4306,7 +4316,7 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
43064316
ADDOP_I(c, CALL_METHOD_KW, argsl + kwdsl);
43074317
}
43084318
else {
4309-
ADDOP_I(c, CALL_METHOD, argsl);
4319+
ADDOP_I(c, CALL_METHOD, argsl);
43104320
}
43114321
c->u->u_lineno = old_lineno;
43124322
return 1;
@@ -4473,7 +4483,7 @@ compiler_subkwargs(struct compiler *c, asdl_keyword_seq *keywords, Py_ssize_t be
44734483
return 1;
44744484
}
44754485

4476-
/* Used by compiler_call_helper and maybe_optimize_method_call to emit
4486+
/* Used by compiler_call_helper and maybe_optimize_method_call to emit
44774487
LOAD_CONST kw1
44784488
LOAD_CONST kw2
44794489
...
@@ -4484,7 +4494,7 @@ Returns 1 on success, 0 on error.
44844494
*/
44854495
static int
44864496
compiler_call_simple_kw_helper(struct compiler *c,
4487-
asdl_keyword_seq *keywords,
4497+
asdl_keyword_seq *keywords,
44884498
Py_ssize_t nkwelts)
44894499
{
44904500
PyObject *names;

0 commit comments

Comments
 (0)