Skip to content

Commit 340cc2a

Browse files
committed
Fix crash on self-referential Generic base (fixes #21549)
class C(Generic[C]) hit "AssertionError: Must not defer during final iteration" because the placeholder for C never resolves. On the final iteration, report an error instead of deferring, matching how other placeholder sites behave. Adds a regression test.
1 parent 8ddae78 commit 340cc2a

2 files changed

Lines changed: 13 additions & 0 deletions

File tree

‎mypy/semanal.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,12 @@ def analyze_unbound_tvar_impl(
24782478
assert not is_unpacked or not is_typealias_param, "Mutually exclusive conditions"
24792479
sym = self.lookup_qualified(t.name, t)
24802480
if sym and isinstance(sym.node, PlaceholderNode):
2481+
if self.final_iteration:
2482+
# The reference can never be resolved (e.g. a class using itself
2483+
# in its own bases: `class C(Generic[C])`). Don't defer here, as
2484+
# that would be an internal error. Fall through so the caller
2485+
# reports a proper error instead.
2486+
return None
24812487
self.record_incomplete_ref()
24822488
if not is_unpacked and sym and isinstance(sym.node, ParamSpecExpr):
24832489
if sym.fullname and not self.tvar_scope.allow_binding(sym.fullname):

‎test-data/unit/semanal-errors.test‎

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

1019+
[case testSelfReferenceInGenericBase]
1020+
from typing import Generic
1021+
class C(Generic[C]): pass \
1022+
# E: Free type variable expected in Generic[...] \
1023+
# E: Cannot resolve name "C" (possible cyclic definition)
1024+
[out]
1025+
10191026
[case testRedeclaredTypeVarWithinNestedGenericClass]
10201027
from typing import Generic, Iterable, TypeVar
10211028
T = TypeVar('T')

0 commit comments

Comments
 (0)