diff --git a/mypy/semanal.py b/mypy/semanal.py index d03e88eaa839..b5c8696c39ec 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2463,7 +2463,10 @@ def analyze_unbound_tvar_impl( assert not is_unpacked or not is_typealias_param, "Mutually exclusive conditions" sym = self.lookup_qualified(t.name, t) if sym and isinstance(sym.node, PlaceholderNode): - self.record_incomplete_ref() + if self.final_iteration: + self.cannot_resolve_name(t.name, "name", t) + else: + self.record_incomplete_ref() if not is_unpacked and sym and isinstance(sym.node, ParamSpecExpr): if sym.fullname and not self.tvar_scope.allow_binding(sym.fullname): # It's bound by our type variable scope diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 8d391d4725e8..e945157d94b3 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -3316,3 +3316,20 @@ class D: ... x: A reveal_type(x) # N: Revealed type is "builtins.str | __main__.D" + +[case testBrokenClassUsingItselfAsTypeVarNoCrash] +from typing import Generic + +class C(Generic[C]): # E: Free type variable expected in Generic[...] \ + # E: Cannot resolve name "C" (possible cyclic definition) + pass + +class D(Generic[E]): # E: Free type variable expected in Generic[...] \ + # E: Cannot resolve name "E" (possible cyclic definition) + pass + +class E(Generic[DD]): # E: Free type variable expected in Generic[...] \ + # E: Cannot resolve name "DD" (possible cyclic definition) + pass + +DD = D # E: Cannot resolve name "DD" (possible cyclic definition) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 8db9e67625d1..b756da6ea9b3 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -2439,6 +2439,12 @@ def test[*Us](*xs: *Us) -> None: 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]?]]" [builtins fixtures/paramspec.pyi] +[case testBrokenClassUsingItselfAsTypeVarNoCrashNewSyntax] +class C[C]: + x: C +c: C[int] +reveal_type(c.x) # N: Revealed type is "builtins.int" + [case testDoubleTypeVarTupleNoCrashNewSyntax] class C[*T, *U](T, U): # E: Can only use one TypeVarTuple in a class definition \ # E: TypeVarTuple "T" is only valid with an unpack \