Skip to content

Commit 99eef8b

Browse files
Handle Self wrapped in Annotated when checking the expected self type (#21928)
Fixes #21917 Self wrapped in Annotated was not being recognized as an expected self type. This PR updates `is_expected_self_type` to recurse through Annotated when checking unbound types.
1 parent cb02891 commit 99eef8b

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

mypy/semanal.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@
259259
)
260260
from mypy.typeops import function_type, get_type_vars, try_getting_str_literals_from_type
261261
from mypy.types import (
262+
ANNOTATED_TYPE_NAMES,
262263
ASSERT_TYPE_NAMES,
263264
DATACLASS_TRANSFORM_NAMES,
264265
DEPRECATED_TYPE_NAMES,
@@ -1190,11 +1191,15 @@ def is_expected_self_type(self, typ: Type, is_classmethod: bool) -> bool:
11901191
sym = self.lookup_qualified(typ.name, typ, suppress_errors=True)
11911192
if sym is not None and sym.fullname in TYPE_NAMES and typ.args:
11921193
return self.is_expected_self_type(typ.args[0], is_classmethod=False)
1194+
if sym is not None and sym.fullname in ANNOTATED_TYPE_NAMES and typ.args:
1195+
return self.is_expected_self_type(typ.args[0], is_classmethod=True)
11931196
return False
11941197
if isinstance(typ, TypeVarType):
11951198
return typ == self.type.self_type
11961199
if isinstance(typ, UnboundType):
11971200
sym = self.lookup_qualified(typ.name, typ, suppress_errors=True)
1201+
if sym is not None and sym.fullname in ANNOTATED_TYPE_NAMES and typ.args:
1202+
return self.is_expected_self_type(typ.args[0], is_classmethod=False)
11981203
return sym is not None and sym.fullname in SELF_TYPE_NAMES
11991204
return False
12001205

test-data/unit/check-selftype.test

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,24 @@ reveal_type(D.meth()) # N: Revealed type is "__main__.D"
15491549
reveal_type(D.bad()) # N: Revealed type is "Never"
15501550
[builtins fixtures/classmethod.pyi]
15511551

1552+
[case testTypingSelfAnnotatedType]
1553+
# See: https://github.com/python/mypy/issues/21917
1554+
1555+
from typing import Self
1556+
from typing_extensions import Annotated
1557+
1558+
class C:
1559+
def foo(self: Annotated[Self, "some_metadata"], x: int) -> None:
1560+
...
1561+
1562+
@classmethod
1563+
def bar(cls: Annotated[type[Self], "some_metadata"], x: int) -> None:
1564+
...
1565+
1566+
reveal_type(C.foo) # N: Revealed type is "def [Self <: __main__.C] (self: Self`2, x: builtins.int)"
1567+
reveal_type(C.bar) # N: Revealed type is "def (x: builtins.int)"
1568+
[builtins fixtures/tuple.pyi]
1569+
15521570
[case testTypingSelfOverload]
15531571
from typing import Self, overload, Union
15541572

0 commit comments

Comments
 (0)