Skip to content

Commit

Permalink
pythongh-109219: propagate used free vars through type param scopes [v2]
Browse files Browse the repository at this point in the history
  • Loading branch information
carljm committed Sep 13, 2023
1 parent baaac99 commit a56116d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
14 changes: 14 additions & 0 deletions Lib/test/test_type_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,20 @@ class Cls:
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):
Expand Down
17 changes: 13 additions & 4 deletions Python/symtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,8 @@ drop_class_free(PySTEntryObject *ste, PyObject *free)
static int
update_symbols(PyObject *symbols, PyObject *scopes,
PyObject *bound, PyObject *free,
PyObject *inlined_cells, int classflag)
PyObject *inlined_cells, int classflag,
PySTEntryObject *class_entry)
{
PyObject *name = NULL, *itr = NULL;
PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL;
Expand Down Expand Up @@ -836,8 +837,16 @@ 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)) {
PyObject *class_v = NULL;
if (class_entry) {
class_v = PyDict_GetItemWithError(class_entry->ste_symbols, name);
if (!class_v && PyErr_Occurred()) {
goto error;
}
}
if ((classflag &&
PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) ||
(class_v && PyLong_AS_LONG(class_v) & (DEF_BOUND | DEF_GLOBAL))) {
long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS;
v_new = PyLong_FromLong(flags);
if (!v_new) {
Expand Down Expand Up @@ -1078,7 +1087,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, class_entry))
goto error;

temp = PyNumber_InPlaceOr(free, newfree);
Expand Down

0 comments on commit a56116d

Please sign in to comment.