From 365297c5240af67acb4798a18135dc87b734477b Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 28 Nov 2022 04:21:34 +0000 Subject: [PATCH] Fix crash in Self type on forward reference in upper bound (#14206) Fixes #14199 This is straightforward, just use the same logic as for regular (user defined) type variables. --- mypy/semanal.py | 6 +++++- test-data/unit/check-classes.test | 15 +++++++++++++++ test-data/unit/check-dataclasses.test | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 698959ca1bdf..3e1e1a1e5d61 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1047,7 +1047,11 @@ def setup_self_type(self) -> None: assert self.type is not None info = self.type if info.self_type is not None: - return + if has_placeholder(info.self_type.upper_bound): + # Similar to regular (user defined) type variables. + self.defer(force_progress=True) + else: + return info.self_type = TypeVarType("Self", f"{info.fullname}.Self", 0, [], fill_typevars(info)) def visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None: diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index e3aea122ebe1..8784c73c5b17 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7679,3 +7679,18 @@ def g(b: Type[Any]) -> None: def h(b: type) -> None: class D(b): ... + +[case testNoCrashOnSelfWithForwardRefGenericClass] +from typing import Generic, Sequence, TypeVar, Self + +_T = TypeVar('_T', bound="Foo") + +class Foo: + foo: int + +class Element(Generic[_T]): + elements: Sequence[Self] + +class Bar(Foo): ... +e: Element[Bar] +reveal_type(e.elements) # N: Revealed type is "typing.Sequence[__main__.Element[__main__.Bar]]" diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index d289ec5a8e58..c248f8db8585 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1981,3 +1981,23 @@ def const_two(x: T) -> str: c = Cont(Box(const_two)) reveal_type(c) # N: Revealed type is "__main__.Cont[builtins.str]" [builtins fixtures/dataclasses.pyi] + +[case testNoCrashOnSelfWithForwardRefGenericDataclass] +from typing import Generic, Sequence, TypeVar, Self +from dataclasses import dataclass + +_T = TypeVar('_T', bound="Foo") + +@dataclass +class Foo: + foo: int + +@dataclass +class Element(Generic[_T]): + elements: Sequence[Self] + +@dataclass +class Bar(Foo): ... +e: Element[Bar] +reveal_type(e.elements) # N: Revealed type is "typing.Sequence[__main__.Element[__main__.Bar]]" +[builtins fixtures/dataclasses.pyi]