From f0fcbcec373a8eaab9cce08f6ce4eb128c13cb44 Mon Sep 17 00:00:00 2001 From: EmmanuelNiyonshuti Date: Thu, 10 Sep 2026 22:04:57 +0200 Subject: [PATCH] Reject type variable whose upper bound is Self --- mypy/message_registry.py | 4 ++++ mypy/semanal.py | 2 ++ test-data/unit/check-python312.test | 7 +++++++ 3 files changed, 13 insertions(+) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 2e40048cbb58b..25530fb9a5dee 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -361,6 +361,10 @@ def with_additional_msg(self, info: str) -> ErrorMessage: "TypeVar constraint type cannot be parametrized by type variables", codes.MISC ) +TYPE_VAR_GENERIC_BOUND_TYPE: Final = ErrorMessage( + "TypeVar upper bound can not be parametrized by type variables", codes.MISC +) + TYPE_VAR_REDECLARED_IN_NESTED_CLASS: Final = ErrorMessage( 'Type variable "{}" is bound by an outer class', codes.VALID_TYPE ) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8d9b001ae7750..ce545838d5afe 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -1899,6 +1899,8 @@ def analyze_type_param( # This and below copies special-casing for old-style type variables, that # is equally necessary for new-style classes to break a vicious circle. upper_bound = PlaceholderType(None, [], context.line) + elif has_type_vars(upper_bound): + self.fail(message_registry.TYPE_VAR_GENERIC_BOUND_TYPE, context) else: if type_param.kind == TYPE_VAR_TUPLE_KIND: upper_bound = self.named_type("builtins.tuple", [self.object_type()]) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 9d612109d5452..d42ab4c3286ad 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -1446,6 +1446,13 @@ 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 testPEP695TypeVariableBoundSelfType] +from typing import Self + +class C: + def foo[T: Self](self: T) -> None: pass # E: TypeVar upper bound can not be parametrized by type variables +[builtins fixtures/tuple.pyi] + [case testPEP695CallAlias] class C: def __init__(self, x: str) -> None: ...