Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-44298: Fix line numbers for early exits in with statements. #26513

Merged
merged 2 commits into from
Jun 3, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions Lib/test/test_sys_settrace.py
Original file line number Diff line number Diff line change
@@ -995,6 +995,52 @@ def func():
(5, 'line'),
(5, 'return')])

def test_early_exit_with(self):

class C:
def __enter__(self):
return self
def __exit__(*args):
pass

def func_break():
for i in (1,2):
with C():
break
pass

def func_return():
with C():
return

self.run_and_compare(func_break,
[(0, 'call'),
(1, 'line'),
(2, 'line'),
(-5, 'call'),
(-4, 'line'),
(-4, 'return'),
(3, 'line'),
(2, 'line'),
(-3, 'call'),
(-2, 'line'),
(-2, 'return'),
(4, 'line'),
(4, 'return')])

self.run_and_compare(func_return,
[(0, 'call'),
(1, 'line'),
(-11, 'call'),
(-10, 'line'),
(-10, 'return'),
(2, 'line'),
(1, 'line'),
(-9, 'call'),
(-8, 'line'),
(-8, 'return'),
(1, 'return')])


class SkipLineEventsTraceTestCase(TraceTestCase):
"""Repeat the trace tests, but with per-line events skipped"""
24 changes: 17 additions & 7 deletions Python/compile.c
Original file line number Diff line number Diff line change
@@ -1796,7 +1796,6 @@ static int
compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
int preserve_tos)
{
int loc;
switch (info->fb_type) {
case WHILE_LOOP:
case EXCEPTION_HANDLER:
@@ -1850,7 +1849,6 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,

case WITH:
case ASYNC_WITH:
loc = c->u->u_lineno;
SET_LOC(c, (stmt_ty)info->fb_datum);
ADDOP(c, POP_BLOCK);
if (preserve_tos) {
@@ -1865,7 +1863,10 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
ADDOP(c, YIELD_FROM);
}
ADDOP(c, POP_TOP);
c->u->u_lineno = loc;
/* The exit block should appear to execute after the
* statement causing the unwinding, so make the unwinding
* instruction artificial */
c->u->u_lineno = -1;
return 1;

case HANDLER_CLEANUP:
@@ -3020,12 +3021,17 @@ compiler_return(struct compiler *c, stmt_ty s)
if (preserve_tos) {
VISIT(c, expr, s->v.Return.value);
} else {
/* Emit instruction with line number for expression */
/* Emit instruction with line number for return value */
if (s->v.Return.value != NULL) {
SET_LOC(c, s->v.Return.value);
ADDOP(c, NOP);
}
}
if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) {
SET_LOC(c, s);
ADDOP(c, NOP);
}

if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL))
return 0;
if (s->v.Return.value == NULL) {
@@ -3044,6 +3050,8 @@ static int
compiler_break(struct compiler *c)
{
struct fblockinfo *loop = NULL;
/* Emit instruction with line number */
ADDOP(c, NOP);
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
return 0;
}
@@ -3062,6 +3070,8 @@ static int
compiler_continue(struct compiler *c)
{
struct fblockinfo *loop = NULL;
/* Emit instruction with line number */
ADDOP(c, NOP);
if (!compiler_unwind_fblock_stack(c, 0, &loop)) {
return 0;
}
@@ -4306,7 +4316,7 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
ADDOP_I(c, CALL_METHOD_KW, argsl + kwdsl);
}
else {
ADDOP_I(c, CALL_METHOD, argsl);
ADDOP_I(c, CALL_METHOD, argsl);
}
c->u->u_lineno = old_lineno;
return 1;
@@ -4473,7 +4483,7 @@ compiler_subkwargs(struct compiler *c, asdl_keyword_seq *keywords, Py_ssize_t be
return 1;
}

/* Used by compiler_call_helper and maybe_optimize_method_call to emit
/* Used by compiler_call_helper and maybe_optimize_method_call to emit
LOAD_CONST kw1
LOAD_CONST kw2
...
@@ -4484,7 +4494,7 @@ Returns 1 on success, 0 on error.
*/
static int
compiler_call_simple_kw_helper(struct compiler *c,
asdl_keyword_seq *keywords,
asdl_keyword_seq *keywords,
Py_ssize_t nkwelts)
{
PyObject *names;
3,540 changes: 1,770 additions & 1,770 deletions Python/importlib.h

Large diffs are not rendered by default.

2,388 changes: 1,194 additions & 1,194 deletions Python/importlib_external.h

Large diffs are not rendered by default.