From df349df9577432e3652312bd6f6a1c7ab184b453 Mon Sep 17 00:00:00 2001 From: wolfgang-aura <169568318+wolfgang-aura@users.noreply.github.com> Date: Wed, 9 Sep 2026 07:01:39 +0800 Subject: [PATCH 1/2] Fix invalid Self in type parameter bounds (#21960) --- mypy/semanal.py | 12 ++++++++++-- test-data/unit/check-selftype.test | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index bceade1b1ac12..877903f1ec1bf 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1888,7 +1888,11 @@ def analyze_type_param( ) -> TypeVarLikeExpr | None: fullname = self.qualified_name(type_param.name) if type_param.upper_bound: - upper_bound = self.anal_type(type_param.upper_bound, allow_placeholder=True) + upper_bound = self.anal_type( + type_param.upper_bound, + allow_placeholder=True, + prohibit_self_type="a type parameter bound", + ) # TODO: we should validate the upper bound is valid for a given kind. if upper_bound is None: # This and below copies special-casing for old-style type variables, that @@ -1929,7 +1933,11 @@ def analyze_type_param( values: list[Type] = [] if type_param.values: for value in type_param.values: - analyzed = self.anal_type(value, allow_placeholder=True) + analyzed = self.anal_type( + value, + allow_placeholder=True, + prohibit_self_type="a type parameter constraint", + ) if analyzed is None: analyzed = PlaceholderType(None, [], context.line) if has_type_vars(analyzed): diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index c157200352562..49d3c228d3b27 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1494,6 +1494,14 @@ def func() -> None: class C(Self): ... # E: Self type is only allowed in annotations within class definition +[case testTypingSelfInvalidLocationsTypeParams] +# flags: --python-version 3.12 +from typing import Self + +class C: + def bounded[T: Self](self: T) -> None: ... # E: Self type cannot be used in a type parameter bound + def constrained[T: (C, Self)](self: T) -> None: ... # E: Self type cannot be used in a type parameter constraint + [case testTypingSelfInvalidArgs] from typing import Self, List From b1f235a13e02e11ec9bcc861992a559007e81ee4 Mon Sep 17 00:00:00 2001 From: wolfgang-aura <169568318+wolfgang-aura@users.noreply.github.com> Date: Wed, 9 Sep 2026 10:49:34 +0800 Subject: [PATCH 2/2] wip: keep PEP 695 Self test on supported runtimes --- test-data/unit/check-python312.test | 8 ++++++++ test-data/unit/check-selftype.test | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 9d612109d5452..bb770a9f09176 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -1446,6 +1446,14 @@ reveal_type(F[str]().m()) # N: Revealed type is "__main__.F[builtins.str]" reveal_type(F[str]().mm(b'x')) # N: Revealed type is "tuple[__main__.F[builtins.str], builtins.bytes]" [builtins fixtures/tuple.pyi] +[case testTypingSelfInvalidLocationsTypeParams] +# flags: --python-version 3.12 +from typing import Self + +class C: + def bounded[T: Self](self: T) -> None: ... # E: Self type cannot be used in a type parameter bound + def constrained[T: (C, Self)](self: T) -> None: ... # E: Self type cannot be used in a type parameter constraint + [case testPEP695CallAlias] class C: def __init__(self, x: str) -> None: ... diff --git a/test-data/unit/check-selftype.test b/test-data/unit/check-selftype.test index 49d3c228d3b27..c157200352562 100644 --- a/test-data/unit/check-selftype.test +++ b/test-data/unit/check-selftype.test @@ -1494,14 +1494,6 @@ def func() -> None: class C(Self): ... # E: Self type is only allowed in annotations within class definition -[case testTypingSelfInvalidLocationsTypeParams] -# flags: --python-version 3.12 -from typing import Self - -class C: - def bounded[T: Self](self: T) -> None: ... # E: Self type cannot be used in a type parameter bound - def constrained[T: (C, Self)](self: T) -> None: ... # E: Self type cannot be used in a type parameter constraint - [case testTypingSelfInvalidArgs] from typing import Self, List