Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1902,7 +1902,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="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
Expand All @@ -1926,6 +1930,7 @@ def analyze_type_param(
allow_tuple_literal=type_param.kind == PARAM_SPEC_KIND,
allow_unpack=type_param.kind == TYPE_VAR_TUPLE_KIND,
analyzing_tvar_def=True,
prohibit_self_type="type parameter default",
)
if default is None:
default = PlaceholderType(None, [], context.line)
Expand All @@ -1943,7 +1948,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="type parameter constraint",
)
if analyzed is None:
analyzed = PlaceholderType(None, [], context.line)
if has_type_vars(analyzed):
Expand Down
17 changes: 17 additions & 0 deletions test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,23 @@ def func() -> None:

class C(Self): ... # E: Self type is only allowed in annotations within class definition

[case testTypingSelfInvalidTypeParamPositions]
# https://github.com/python/mypy/issues/21960
# flags: --python-version 3.13
from typing import Self

class Foo:
def meth[T: Self](self: T) -> None: ... # E: Self type cannot be used in type parameter bound

class Bar[T: Self]: ... # E: Self type cannot be used in type parameter bound

def func[T: (Self, int)](x: T) -> None: ... # E: Self type cannot be used in type parameter constraint

type Alias[T: Self] = list[T] # E: Self type cannot be used in type parameter bound

class Ok[T]:
def meth(self: Self) -> None: ...

[case testTypingSelfInvalidArgs]
from typing import Self, List

Expand Down
Loading