]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-109219: propagate free vars through type param scopes (GH-109377) (#109410)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 14 Sep 2023 22:42:39 +0000 (15:42 -0700)
committerGitHub <noreply@github.com>
Thu, 14 Sep 2023 22:42:39 +0000 (00:42 +0200)
gh-109219: propagate free vars through type param scopes (GH-109377)
(cherry picked from commit 909adb5092c0ae9426814742d97932204b211cfb)

Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Lib/test/test_type_params.py
Misc/NEWS.d/next/Core and Builtins/2023-09-13-08-42-45.gh-issue-109219.UiN8sc.rst [new file with mode: 0644]
Python/symtable.c

index b1848aee4753a1ff7f67c9ac4078b1bfd9cab2c4..25ee188731f31fbe9762c5d7cd882e11c5225ec0 100644 (file)
@@ -694,6 +694,19 @@ class TypeParamsClassScopeTest(unittest.TestCase):
         cls = ns["outer"]()
         self.assertEqual(cls.Alias.__value__, "class")
 
+    def test_nested_free(self):
+        ns = run_code("""
+            def f():
+                T = str
+                class C:
+                    T = int
+                    class D[U](T):
+                        x = T
+                return C
+        """)
+        C = ns["f"]()
+        self.assertIn(int, C.D.__bases__)
+        self.assertIs(C.D.x, str)
 
 class TypeParamsManglingTest(unittest.TestCase):
     def test_mangling(self):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-13-08-42-45.gh-issue-109219.UiN8sc.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-13-08-42-45.gh-issue-109219.UiN8sc.rst
new file mode 100644 (file)
index 0000000..2c141f0
--- /dev/null
@@ -0,0 +1,2 @@
+Fix compiling type param scopes that use a name which is also free in an
+inner scope.
index 691698e00b4619b59ac476812c62a7daab6cbfd6..4989e03d4bf591f8e67b2b9ad3bd44ac432a6d39 100644 (file)
@@ -801,8 +801,7 @@ update_symbols(PyObject *symbols, PyObject *scopes,
                the class that has the same name as a local
                or global in the class scope.
             */
-            if  (classflag &&
-                 PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) {
+            if  (classflag) {
                 long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS;
                 v_new = PyLong_FromLong(flags);
                 if (!v_new) {
@@ -1037,7 +1036,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,
         goto error;
     /* Records the results of the analysis in the symbol table entry */
     if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, inlined_cells,
-                        ste->ste_type == ClassBlock))
+                        (ste->ste_type == ClassBlock) || ste->ste_can_see_class_scope))
         goto error;
 
     temp = PyNumber_InPlaceOr(free, newfree);