From d7b88cc6bf5498dff56b351a6a037779513579df Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 16 Jul 2025 15:43:03 +0200 Subject: [PATCH 1/5] use plain_self as subtitution type for self --- mypy/subtypes.py | 3 ++- test-data/unit/check-python312.test | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 428e6dec6749..42711444d1ec 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -2208,7 +2208,8 @@ def infer_variance(info: TypeInfo, i: int) -> bool: settable = False # TODO: handle settable properties with setter type different from getter. - typ = find_member(member, self_type, self_type) + plain_self = Instance(info.mro[0], []) # self-type without type variables + typ = find_member(member, self_type, plain_self) if typ: # It's okay for a method in a generic class with a contravariant type # variable to return a generic instance of the class, if it doesn't involve diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index bfd6334b5077..7da91a930b0c 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -450,6 +450,21 @@ class Contra2[T]: d1: Contra2[int] = Contra2[float]() d2: Contra2[float] = Contra2[int]() # E: Incompatible types in assignment (expression has type "Contra2[int]", variable has type "Contra2[float]") +[case testPEP695InferVariancePolymorphicMethod] +class Cov[T]: + def get(self) -> T: ... + def new[S](self: "Cov[S]", arg: list[S]) -> "Cov[S]": ... + +cov_pos: Cov[object] = Cov[int]() +cov_neg: Cov[int] = Cov[object]() # E: Incompatible types in assignment (expression has type "Cov[object]", variable has type "Cov[int]") + +class Contra[T]: + def set(self, arg: T) -> None: ... + def new[S](self: "Contra[S]", arg: list[S]) -> "Contra[S]": ... + +contra_pos: Contra[object] = Contra[int]() # E: Incompatible types in assignment (expression has type "Contra[int]", variable has type "Contra[object]") +contra_neg: Contra[int] = Contra[object]() + [case testPEP695InheritInvariant] class Invariant[T]: x: T From a0b037eec1405a69528a8de531ac98324a598831 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Wed, 16 Jul 2025 17:42:19 +0200 Subject: [PATCH 2/5] Update mypy/subtypes.py Co-authored-by: Stanislav Terliakov <50529348+sterliakov@users.noreply.github.com> --- mypy/subtypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/subtypes.py b/mypy/subtypes.py index 42711444d1ec..3c49af722880 100644 --- a/mypy/subtypes.py +++ b/mypy/subtypes.py @@ -2208,7 +2208,7 @@ def infer_variance(info: TypeInfo, i: int) -> bool: settable = False # TODO: handle settable properties with setter type different from getter. - plain_self = Instance(info.mro[0], []) # self-type without type variables + plain_self = fill_typevars_with_any(info) # self-type without type variables typ = find_member(member, self_type, plain_self) if typ: # It's okay for a method in a generic class with a contravariant type From 0b2aead8a4aa1ca30ef7d0ed480ae787b56bf446 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Tue, 16 Sep 2025 14:47:59 +0200 Subject: [PATCH 3/5] added unit test for 18334 --- test-data/unit/check-python312.test | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 37fed3b6d3fa..e4f498fb85e8 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -465,6 +465,21 @@ class Contra[T]: contra_pos: Contra[object] = Contra[int]() # E: Incompatible types in assignment (expression has type "Contra[int]", variable has type "Contra[object]") contra_neg: Contra[int] = Contra[object]() + +[case testPEP695SelfAttribute] +# https://github.com/python/mypy/issues/18334 +from typing import Self + +class Foo[T]: + instance: Self + def foo(self) -> T: ... # type:ignore[empty-body] + +class Bar(Foo[int]): ... + +# OK +foo: Foo[object] = Bar() + + [case testPEP695InheritInvariant] class Invariant[T]: x: T From 9bdec3c3f6bde77573a44f1f594177526d85dfaf Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Mon, 9 Mar 2026 20:11:21 +0100 Subject: [PATCH 4/5] Add test case for PEP 695 Self return type with Union in check-python312.test --- test-data/unit/check-python312.test | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index a3a1bd01b076..d0ccfe8e92fb 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -480,6 +480,19 @@ class Bar(Foo[int]): ... foo: Foo[object] = Bar() +[case testPEP695SelfReturnTypeWithUnion] +# https://github.com/python/mypy/issues/20997 +from typing import Protocol, Self + +class ComplexScalar: ... + +class FloatScalar[FloatT](Protocol): + def pow(self, arg: FloatT) -> Self | ComplexScalar: ... + +def upcast(arg: FloatScalar[object]) -> FloatScalar[float]: + return arg + + [case testPEP695InheritInvariant] class Invariant[T]: x: T From d2d84915527ce0cec9f7072d59971aeaa7634fdd Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Tue, 10 Mar 2026 09:36:14 +0100 Subject: [PATCH 5/5] Remove Protocol inheritance from FloatScalar class in check-python312.test --- test-data/unit/check-python312.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index d0ccfe8e92fb..2cb09928a760 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -482,11 +482,11 @@ foo: Foo[object] = Bar() [case testPEP695SelfReturnTypeWithUnion] # https://github.com/python/mypy/issues/20997 -from typing import Protocol, Self +from typing import Self class ComplexScalar: ... -class FloatScalar[FloatT](Protocol): +class FloatScalar[FloatT]: def pow(self, arg: FloatT) -> Self | ComplexScalar: ... def upcast(arg: FloatScalar[object]) -> FloatScalar[float]: