Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fe2e1f5

Browse files
committed
Reject Self in PEP 695 type parameter bounds (#21960)
PEP 673 lists the valid locations for Self, and a PEP 695 type parameter bound is not one of them. mypy accepted it silently: class C: def bounded[T: Self](self: T) -> None: ... reported no error at all. Analysing the bound with prohibit_self_type gives the same message mypy already uses for the other invalid locations. The constraint case is also covered. mypy already rejected it, but as "TypeVar constraint type cannot be parametrized by type variables", which names the wrong reason.
1 parent ae39cdb commit fe2e1f5

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

mypy/semanal.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,7 +1888,11 @@ def analyze_type_param(
18881888
) -> TypeVarLikeExpr | None:
18891889
fullname = self.qualified_name(type_param.name)
18901890
if type_param.upper_bound:
1891-
upper_bound = self.anal_type(type_param.upper_bound, allow_placeholder=True)
1891+
upper_bound = self.anal_type(
1892+
type_param.upper_bound,
1893+
allow_placeholder=True,
1894+
prohibit_self_type="a type parameter bound",
1895+
)
18921896
# TODO: we should validate the upper bound is valid for a given kind.
18931897
if upper_bound is None:
18941898
# This and below copies special-casing for old-style type variables, that
@@ -1929,7 +1933,11 @@ def analyze_type_param(
19291933
values: list[Type] = []
19301934
if type_param.values:
19311935
for value in type_param.values:
1932-
analyzed = self.anal_type(value, allow_placeholder=True)
1936+
analyzed = self.anal_type(
1937+
value,
1938+
allow_placeholder=True,
1939+
prohibit_self_type="a type parameter constraint",
1940+
)
19331941
if analyzed is None:
19341942
analyzed = PlaceholderType(None, [], context.line)
19351943
if has_type_vars(analyzed):

test-data/unit/check-python312.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,14 @@ reveal_type(F[str]().m()) # N: Revealed type is "__main__.F[builtins.str]"
14461446
reveal_type(F[str]().mm(b'x')) # N: Revealed type is "tuple[__main__.F[builtins.str], builtins.bytes]"
14471447
[builtins fixtures/tuple.pyi]
14481448

1449+
[case testTypingSelfInvalidLocationsTypeParams]
1450+
# flags: --python-version 3.12
1451+
from typing import Self
1452+
1453+
class C:
1454+
def bounded[T: Self](self: T) -> None: ... # E: Self type cannot be used in a type parameter bound
1455+
def constrained[T: (C, Self)](self: T) -> None: ... # E: Self type cannot be used in a type parameter constraint
1456+
14491457
[case testPEP695CallAlias]
14501458
class C:
14511459
def __init__(self, x: str) -> None: ...

0 commit comments

Comments
 (0)