From de8e52972211f02e38d751b13842c13377d003bd Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 10 Jun 2024 22:29:04 +0100 Subject: [PATCH 1/5] gh-93691: fix too broad source locations of for statement iterators --- Lib/test/test_iter.py | 46 +++++++++++++++++++++++++++++++++++++++++++ Python/compile.c | 1 + 2 files changed, 47 insertions(+) diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py index 9606d5beab71cb..ec2b68acb90785 100644 --- a/Lib/test/test_iter.py +++ b/Lib/test/test_iter.py @@ -10,6 +10,7 @@ import functools import contextlib import builtins +import traceback # Test result of triple loop (too big to inline) TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2), @@ -1143,6 +1144,51 @@ def test_error_iter(self): self.assertRaises(TypeError, iter, typ()) self.assertRaises(ZeroDivisionError, iter, BadIterableClass()) + def test_exception_locations(self): + # The location of an exception raised from __init__ or + # __next__ should should be the iterator expression + + class Iter: + def __init__(self, init_raises=False, next_raises=False): + if init_raises: + 1/0 + self.next_raises = next_raises + + def __next__(self): + if self.next_raises: + 1/0 + + def __iter__(self): + return self + + def init_raises(): + try: + for x in Iter(init_raises=True): + pass + except Exception as e: + return e + + def next_raises(): + try: + for x in Iter(next_raises=True): + pass + except Exception as e: + return e + + for func, expected in [(init_raises, "Iter(init_raises=True)"), + (next_raises, "Iter(next_raises=True)"), + ]: + with self.subTest(func): + exc = func() + f = traceback.extract_tb(exc.__traceback__)[0] + indent = 16 + co = func.__code__ + self.assertEqual(f.lineno, co.co_firstlineno + 2) + self.assertEqual(f.end_lineno, co.co_firstlineno + 2) + self.assertEqual(f.line[f.colno - indent : f.end_colno - indent], + expected) + + if __name__ == "__main__": unittest.main() diff --git a/Python/compile.c b/Python/compile.c index cb724154206b7e..0e3ca0bf2c8a8c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2981,6 +2981,7 @@ compiler_for(struct compiler *c, stmt_ty s) RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL)); VISIT(c, expr, s->v.For.iter); + loc = LOC(s->v.For.iter); ADDOP(c, loc, GET_ITER); USE_LABEL(c, start); From f067774df62e771b67cc832fa284d5e3e6965091 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 10 Jun 2024 22:31:02 +0100 Subject: [PATCH 2/5] add news --- .../2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst new file mode 100644 index 00000000000000..294f8d892b459b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst @@ -0,0 +1,2 @@ +Fix source locations of instructions generated for the iterator of a for +statement. From 6a3386c7be53afa0427f44fe1aa4ff0cf57772e6 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 10 Jun 2024 23:14:41 +0100 Subject: [PATCH 3/5] regen-all --- Programs/test_frozenmain.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index cdc417e48ebec6..f34d7ea0789310 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -27,12 +27,11 @@ unsigned char M_test_frozenmain[] = { 3,0,0,0,218,3,107,101,121,169,0,243,0,0,0,0, 218,18,116,101,115,116,95,102,114,111,122,101,110,109,97,105, 110,46,112,121,218,8,60,109,111,100,117,108,101,62,114,18, - 0,0,0,1,0,0,0,115,99,0,0,0,240,3,1,1, + 0,0,0,1,0,0,0,115,94,0,0,0,240,3,1,1, 1,243,8,0,1,11,219,0,24,225,0,5,208,6,26,212, 0,27,217,0,5,128,106,144,35,151,40,145,40,212,0,27, 216,9,26,215,9,38,210,9,38,211,9,40,168,24,209,9, - 50,128,6,240,2,6,12,2,242,0,7,1,42,128,67,241, - 14,0,5,10,136,71,144,67,144,53,152,2,152,54,160,35, - 153,59,152,45,208,10,40,214,4,41,242,15,7,1,42,114, - 16,0,0,0, + 50,128,6,243,2,6,12,2,128,67,241,14,0,5,10,136, + 71,144,67,144,53,152,2,152,54,160,35,153,59,152,45,208, + 10,40,214,4,41,242,15,6,12,2,114,16,0,0,0, }; From 8aa33e18b4a4eaebbc170646e6137de14361e94c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 11 Jun 2024 10:57:24 +0100 Subject: [PATCH 4/5] fix line tracing of multiline for statements --- Lib/test/test_sys_settrace.py | 6 +++--- Python/compile.c | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index ded1d9224d82d9..c622fd9ce7c466 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -1650,15 +1650,15 @@ def func(): EXPECTED_EVENTS = [ (0, 'call'), (2, 'line'), - (1, 'line'), (-3, 'call'), (-2, 'line'), (-2, 'return'), - (4, 'line'), (1, 'line'), + (4, 'line'), + (2, 'line'), (-2, 'call'), (-2, 'return'), - (1, 'return'), + (2, 'return'), ] # C level events should be the same as expected and the same as Python level. diff --git a/Python/compile.c b/Python/compile.c index 0e3ca0bf2c8a8c..e1a2b0247b49ef 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2981,12 +2981,18 @@ compiler_for(struct compiler *c, stmt_ty s) RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL)); VISIT(c, expr, s->v.For.iter); + loc = LOC(s->v.For.iter); ADDOP(c, loc, GET_ITER); USE_LABEL(c, start); ADDOP_JUMP(c, loc, FOR_ITER, cleanup); + /* Add NOP to ensure correct line tracing of multiline for statements. + * It will be removed later if redundant. + */ + ADDOP(c, LOC(s->v.For.target), NOP); + USE_LABEL(c, body); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); From 6a9ca6d0c69603228ce2c825ca9f72d5fcaa0574 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 11 Jun 2024 11:04:11 +0100 Subject: [PATCH 5/5] update codegen test --- Lib/test/test_compiler_codegen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_compiler_codegen.py b/Lib/test/test_compiler_codegen.py index 1088b4aa9e624d..d82fb85ed259ab 100644 --- a/Lib/test/test_compiler_codegen.py +++ b/Lib/test/test_compiler_codegen.py @@ -49,6 +49,7 @@ def test_for_loop(self): ('GET_ITER', None, 1), loop_lbl := self.Label(), ('FOR_ITER', exit_lbl := self.Label(), 1), + ('NOP', None, 1, 1), ('STORE_NAME', 1, 1), ('LOAD_NAME', 2, 2), ('PUSH_NULL', None, 2),