From 037bd3c7b5cccd9c15d6459a614b9f85daed5435 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Sun, 27 Nov 2022 19:58:31 +0000 Subject: [PATCH] Fix crash in Self type on forward reference in upper bound --- 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 698959ca1bdff..3e1e1a1e5d611 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 e3aea122ebe1b..8784c73c5b175 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 d289ec5a8e58d..c248f8db85854 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]