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
18 changes: 16 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="a type variable 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 Down Expand Up @@ -5067,7 +5071,13 @@ def process_typevar_parameters(
if has_values:
self.fail("TypeVar cannot have both values and an upper bound", context)
return None
tv_arg = self.get_typevarlike_argument("TypeVar", param_name, param_value, context)
tv_arg = self.get_typevarlike_argument(
"TypeVar",
param_name,
param_value,
context,
prohibit_self_type="a type variable bound",
)
if tv_arg is None:
return None
upper_bound = tv_arg
Expand Down Expand Up @@ -5119,6 +5129,7 @@ def get_typevarlike_argument(
allow_param_spec_literals: bool = False,
allow_unpack: bool = False,
report_invalid_typevar_arg: bool = True,
prohibit_self_type: str | None = None,
) -> Type | None:
try:
# We want to use our custom error message below, so we suppress
Expand All @@ -5131,6 +5142,7 @@ def get_typevarlike_argument(
allow_param_spec_literals=allow_param_spec_literals,
allow_unpack=allow_unpack,
analyzing_tvar_def=param_name == "default",
prohibit_self_type=prohibit_self_type,
)
if analyzed is None:
# Type variables are special: we need to place them in the symbol table
Expand Down Expand Up @@ -7824,6 +7836,7 @@ def expr_to_analyzed_type(
allow_unpack: bool = False,
unique_name: str | None = None,
analyzing_tvar_def: bool = False,
prohibit_self_type: str | None = None,
) -> Type | None:
if unique_name is not None and isinstance(expr, CallExpr):
# This is a legacy syntax intended mostly for Python 2, we keep it for
Expand Down Expand Up @@ -7856,6 +7869,7 @@ def expr_to_analyzed_type(
allow_param_spec_literals=allow_param_spec_literals,
allow_unpack=allow_unpack,
analyzing_tvar_def=analyzing_tvar_def,
prohibit_self_type=prohibit_self_type,
)

def analyze_type_expr(self, expr: Expression) -> None:
Expand Down
12 changes: 12 additions & 0 deletions test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,18 @@ def func() -> None:

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

[case testTypingSelfInvalidAsTypeParameterBound]
# flags: --python-version 3.12
from typing import Self, TypeVar

class C:
def f[T: Self](self, x: T) -> T: ... # E: Self type cannot be used in a type variable bound

class D:
T = TypeVar("T", bound=Self) # E: Self type cannot be used in a type variable bound # E: TypeVar "bound" must be a type

class E[T: Self]: ... # E: Self type cannot be used in a type variable bound

[case testTypingSelfInvalidArgs]
from typing import Self, List

Expand Down
Loading