]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-93691: fix too broad source locations of for statement iterators (GH-120330...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Thu, 13 Jun 2024 10:38:36 +0000 (11:38 +0100)
committerGitHub <noreply@github.com>
Thu, 13 Jun 2024 10:38:36 +0000 (11:38 +0100)
[3.12] gh-93691: fix too broad source locations of for statement iterators (GH-120330).
(cherry picked from commit 97b69db167be28a33688db436551a6c3c3ea4662)

Lib/test/test_compiler_codegen.py
Lib/test/test_iter.py
Lib/test/test_sys_settrace.py
Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst [new file with mode: 0644]
Programs/test_frozenmain.h
Python/compile.c

index ea57df9cd2400b8bc37166f49edfec6d6ca951f9..a1794980dcd240a9d93bfe738da1477f708db925 100644 (file)
@@ -39,6 +39,7 @@ class IsolatedCodeGenTests(CodegenTestCase):
             ('GET_ITER', None, 1),
             loop_lbl := self.Label(),
             ('FOR_ITER', exit_lbl := self.Label(), 1),
+            ('NOP', None, 1, 1),
             ('STORE_NAME', 1, 1),
             ('PUSH_NULL', None, 2),
             ('LOAD_NAME', 2, 2),
index 9606d5beab71cb0a4990c6acb42a17bf3d942b73..ec2b68acb9078567621ff33a08728dce9210d007 100644 (file)
@@ -10,6 +10,7 @@ import collections.abc
 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 @@ class TestCase(unittest.TestCase):
             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()
index 196fd60d1973f61e2659eb34ae625cce1512d3da..35985b34a42cf52f6e44825392e3044e8b610439 100644 (file)
@@ -1634,15 +1634,15 @@ class TraceTestCase(unittest.TestCase):
         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/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 (file)
index 0000000..294f8d8
--- /dev/null
@@ -0,0 +1,2 @@
+Fix source locations of instructions generated for the iterator of a for
+statement.
index cd9d1032629f49be4b18ac445acd77495b84f9ba..8c7cb58fbfd3c252a50501b353e51ffbba23d965 100644 (file)
@@ -27,12 +27,11 @@ unsigned char M_test_frozenmain[] = {
     218,3,107,101,121,169,0,243,0,0,0,0,250,18,116,101,
     115,116,95,102,114,111,122,101,110,109,97,105,110,46,112,121,
     250,8,60,109,111,100,117,108,101,62,114,18,0,0,0,1,
-    0,0,0,115,102,0,0,0,240,3,1,1,1,243,8,0,
+    0,0,0,115,97,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,38,208,
     9,26,215,9,38,209,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,213,4,41,241,15,7,1,42,114,16,
-    0,0,0,
+    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,213,4,41,241,15,6,12,2,114,16,0,0,0,
 };
index 0cd8d6082ebfeb6dd38d45c8db67aa0e7415c59f..5e96a9665618e562784c6134d6e2d292c6bd6c0b 100644 (file)
@@ -3024,11 +3024,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);