diff --git a/mypy/message_registry.py b/mypy/message_registry.py index 2e40048cbb58..25530fb9a5de 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 8d9b001ae775..ce545838d5af 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 9d612109d545..d42ab4c3286a 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: ...