Skip to content

Commit 58a63c9

Browse files
authored
Fix crash on class using itself as a type variable (#22219)
Fixes #21549 Fix is straightforward. New syntax test added just in case for completeness.
1 parent 351a61f commit 58a63c9

3 files changed

Lines changed: 27 additions & 1 deletion

File tree

‎mypy/semanal.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2463,7 +2463,10 @@ def analyze_unbound_tvar_impl(
24632463
assert not is_unpacked or not is_typealias_param, "Mutually exclusive conditions"
24642464
sym = self.lookup_qualified(t.name, t)
24652465
if sym and isinstance(sym.node, PlaceholderNode):
2466-
self.record_incomplete_ref()
2466+
if self.final_iteration:
2467+
self.cannot_resolve_name(t.name, "name", t)
2468+
else:
2469+
self.record_incomplete_ref()
24672470
if not is_unpacked and sym and isinstance(sym.node, ParamSpecExpr):
24682471
if sym.fullname and not self.tvar_scope.allow_binding(sym.fullname):
24692472
# It's bound by our type variable scope

‎test-data/unit/check-newsemanal.test‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,3 +3316,20 @@ class D: ...
33163316

33173317
x: A
33183318
reveal_type(x) # N: Revealed type is "builtins.str | __main__.D"
3319+
3320+
[case testBrokenClassUsingItselfAsTypeVarNoCrash]
3321+
from typing import Generic
3322+
3323+
class C(Generic[C]): # E: Free type variable expected in Generic[...] \
3324+
# E: Cannot resolve name "C" (possible cyclic definition)
3325+
pass
3326+
3327+
class D(Generic[E]): # E: Free type variable expected in Generic[...] \
3328+
# E: Cannot resolve name "E" (possible cyclic definition)
3329+
pass
3330+
3331+
class E(Generic[DD]): # E: Free type variable expected in Generic[...] \
3332+
# E: Cannot resolve name "DD" (possible cyclic definition)
3333+
pass
3334+
3335+
DD = D # E: Cannot resolve name "DD" (possible cyclic definition)

‎test-data/unit/check-python312.test‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,12 @@ def test[*Us](*xs: *Us) -> None:
24392439
reveal_type(print_args(2, *xs, 4)) # N: Revealed type is "__main__.C[[Literal[2]?, *args: *tuple[*Us, Literal[4]?]], tuple[Literal[2]?, *Us, Literal[4]?]]"
24402440
[builtins fixtures/paramspec.pyi]
24412441

2442+
[case testBrokenClassUsingItselfAsTypeVarNoCrashNewSyntax]
2443+
class C[C]:
2444+
x: C
2445+
c: C[int]
2446+
reveal_type(c.x) # N: Revealed type is "builtins.int"
2447+
24422448
[case testDoubleTypeVarTupleNoCrashNewSyntax]
24432449
class C[*T, *U](T, U): # E: Can only use one TypeVarTuple in a class definition \
24442450
# E: TypeVarTuple "T" is only valid with an unpack \

0 commit comments

Comments
 (0)