Skip to content

Commit 35a09ea

Browse files
committed
Fix missing error when redeclaring type variable in nested generic class
1 parent e867132 commit 35a09ea

File tree

4 files changed

+19
-5
lines changed

4 files changed

+19
-5
lines changed

mypy/message_registry.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
354354
"TypeVar constraint type cannot be parametrized by type variables", codes.MISC
355355
)
356356

357+
TYPE_VAR_REDECLARED_IN_NESTED_CLASS: Final = ErrorMessage(
358+
'Type variable "{}" is bound by an outer class', codes.VALID_TYPE
359+
)
360+
357361
TYPE_ALIAS_WITH_YIELD_EXPRESSION: Final = ErrorMessage(
358362
"Yield expression cannot be used within a type alias", codes.SYNTAX
359363
)

mypy/semanal.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,14 @@ def tvar_defs_from_tvars(
23872387
tvar_expr.default = tvar_expr.default.accept(
23882388
TypeVarDefaultTranslator(self, tvar_expr.name, context)
23892389
)
2390+
# PEP-695 type variables that are redeclared in an inner scope are warned
2391+
# about elsewhere.
2392+
if not tvar_expr.is_new_style and not self.tvar_scope.allow_binding(
2393+
tvar_expr.fullname
2394+
):
2395+
self.fail(
2396+
message_registry.TYPE_VAR_REDECLARED_IN_NESTED_CLASS.format(name), context
2397+
)
23902398
tvar_def = self.tvar_scope.bind_new(name, tvar_expr)
23912399
if last_tvar_name_with_default is not None and not tvar_def.has_default():
23922400
self.msg.tvar_without_default_type(

mypy/typeanal.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,11 +1869,7 @@ def bind_function_type_variables(
18691869
defs = []
18701870
for name, tvar in typevars:
18711871
if not self.tvar_scope.allow_binding(tvar.fullname):
1872-
self.fail(
1873-
f'Type variable "{name}" is bound by an outer class',
1874-
defn,
1875-
code=codes.VALID_TYPE,
1876-
)
1872+
self.fail(message_registry.TYPE_VAR_REDECLARED_IN_NESTED_CLASS.format(name), defn)
18771873
binding = self.tvar_scope.bind_new(name, tvar)
18781874
defs.append(binding)
18791875

test-data/unit/semanal-errors.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,12 @@ class A(Generic[T]):
10151015
# E: Free type variable expected in Generic[...]
10161016
[out]
10171017

1018+
[case testRedeclaredTypeVarWithinNestedGenericClass]
1019+
from typing import Generic, Iterable, TypeVar
1020+
T = TypeVar('T')
1021+
class A(Generic[T]):
1022+
class B(Iterable[T]): pass # E: Type variable "T" is bound by an outer class
1023+
10181024
[case testIncludingGenericTwiceInBaseClassList]
10191025
from typing import Generic, TypeVar
10201026
T = TypeVar('T')

0 commit comments

Comments
 (0)