Skip to content

Commit 8a8853a

Browse files
gh-104640: Disallow walrus in comprehension within type scopes (#104641)
1 parent ab8f546 commit 8a8853a

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

Lib/test/test_type_params.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ def test_disallowed_expressions(self):
136136
check_syntax_error(self, "class X[T: (y := 3)]: pass")
137137
check_syntax_error(self, "class X[T](y := Sequence[T]): pass")
138138
check_syntax_error(self, "def f[T](y: (x := Sequence[T])): pass")
139+
check_syntax_error(self, "class X[T]([(x := 3) for _ in range(2)] and B): pass")
140+
check_syntax_error(self, "def f[T: [(x := 3) for _ in range(2)]](): pass")
141+
check_syntax_error(self, "type T = [(x := 3) for _ in range(2)]")
139142

140143

141144
class TypeParamsNonlocalTest(unittest.TestCase):

Python/symtable.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@
3535
#define NAMED_EXPR_COMP_IN_CLASS \
3636
"assignment expression within a comprehension cannot be used in a class body"
3737

38+
#define NAMED_EXPR_COMP_IN_TYPEVAR_BOUND \
39+
"assignment expression within a comprehension cannot be used in a TypeVar bound"
40+
41+
#define NAMED_EXPR_COMP_IN_TYPEALIAS \
42+
"assignment expression within a comprehension cannot be used in a type alias"
43+
44+
#define NAMED_EXPR_COMP_IN_TYPEPARAM \
45+
"assignment expression within a comprehension cannot be used within the definition of a generic"
46+
3847
#define NAMED_EXPR_COMP_CONFLICT \
3948
"assignment expression cannot rebind comprehension iteration variable '%U'"
4049

@@ -1857,7 +1866,7 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
18571866
}
18581867

18591868
/* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */
1860-
if (_PyST_IsFunctionLike(ste)) {
1869+
if (ste->ste_type == FunctionBlock) {
18611870
long target_in_scope = _PyST_GetSymbol(ste, target_name);
18621871
if (target_in_scope & DEF_GLOBAL) {
18631872
if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))
@@ -1880,9 +1889,27 @@ symtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)
18801889

18811890
return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e));
18821891
}
1883-
/* Disallow usage in ClassBlock */
1884-
if (ste->ste_type == ClassBlock) {
1885-
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS);
1892+
/* Disallow usage in ClassBlock and type scopes */
1893+
if (ste->ste_type == ClassBlock ||
1894+
ste->ste_type == TypeParamBlock ||
1895+
ste->ste_type == TypeAliasBlock ||
1896+
ste->ste_type == TypeVarBoundBlock) {
1897+
switch (ste->ste_type) {
1898+
case ClassBlock:
1899+
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS);
1900+
break;
1901+
case TypeParamBlock:
1902+
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEPARAM);
1903+
break;
1904+
case TypeAliasBlock:
1905+
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEALIAS);
1906+
break;
1907+
case TypeVarBoundBlock:
1908+
PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEVAR_BOUND);
1909+
break;
1910+
default:
1911+
Py_UNREACHABLE();
1912+
}
18861913
PyErr_RangedSyntaxLocationObject(st->st_filename,
18871914
e->lineno,
18881915
e->col_offset + 1,

0 commit comments

Comments
 (0)