summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2024-06-12 11:53:19 (GMT)
committerGitHub <noreply@github.com>2024-06-12 11:53:19 (GMT)
commit97b69db167be28a33688db436551a6c3c3ea4662 (patch)
treef330280cdb1e39fc5277ae014eb959034154d07d
parent755dab719dfc924dd8aef46f67512dabb8f25071 (diff)
downloadcpython-97b69db167be28a33688db436551a6c3c3ea4662.zip
cpython-97b69db167be28a33688db436551a6c3c3ea4662.tar.gz
cpython-97b69db167be28a33688db436551a6c3c3ea4662.tar.bz2
gh-93691: fix too broad source locations of for statement iterators (#120330)
-rw-r--r--Lib/test/test_compiler_codegen.py1
-rw-r--r--Lib/test/test_iter.py46
-rw-r--r--Lib/test/test_sys_settrace.py6
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-06-10-22-30-26.gh-issue-93691.68WOTS.rst2
-rw-r--r--Programs/test_frozenmain.h9
-rw-r--r--Python/compile.c7
6 files changed, 63 insertions, 8 deletions
diff --git a/Lib/test/test_compiler_codegen.py b/Lib/test/test_compiler_codegen.py
index 1088b4a..d82fb85 100644
--- a/Lib/test/test_compiler_codegen.py
+++ b/Lib/test/test_compiler_codegen.py
@@ -49,6 +49,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),
('LOAD_NAME', 2, 2),
('PUSH_NULL', None, 2),
diff --git a/Lib/test/test_iter.py b/Lib/test/test_iter.py
index 9606d5b..ec2b68a 100644
--- a/Lib/test/test_iter.py
+++ b/Lib/test/test_iter.py
@@ -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()
diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py
index ded1d92..c622fd9 100644
--- a/Lib/test/test_sys_settrace.py
+++ b/Lib/test/test_sys_settrace.py
@@ -1650,15 +1650,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
index 0000000..294f8d8
--- /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.
diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h
index cdc417e..f34d7ea 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,
};
diff --git a/Python/compile.c b/Python/compile.c
index c337276..749b69f 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3025,11 +3025,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);