You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
@cache breaks type checking when used with @classmethod and typing.Self #19117
Title
@cache breaks type checking when used with @classmethod and typing.Self
Bug description
Using @functools.cache on a @classmethod that returns typing.Self breaks type inference in mypy and IntelliSense. mypy either falls back to Any or fails type inference entirely.
Illustrative repro
fromfunctoolsimportcachefromtypingimportSelfclassMyProvider:
@classmethod@cachedefget_by_name(cls, name: str) ->Self:
...
provider=MyProvider.get_by_name("foo")
reveal_type(provider) # mypy: Revealed type is "Any"
Without @cache (works as expected)
classMyProvider:
@classmethoddefget_by_name(cls, name: str) ->Self:
...
provider=MyProvider.get_by_name("foo")
reveal_type(provider) # mypy: Revealed type is "MyProvider"
With @cache and concrete return type (also works)
classMyProvider:
@classmethod@cachedefget_by_name(cls, name: str) ->MyProvider:
...
provider=MyProvider.get_by_name("foo")
reveal_type(provider) # mypy: Revealed type is "MyProvider"
Summary
This shows that Self return types on cached classmethods are not handled correctly by mypy. Replacing Self with the concrete class is a workaround, but sacrifices subclassing flexibility.
Environment
Python: 3.11 (per pyproject.toml)
mypy: 1.8+ (as specified in poetry.lock)
Flags: --strict
Editor: VSCode (optional, but IntelliSense also affected)
Related
Possibly related: python/typeshed#11280 (but that focuses on general decorator signature issues — this case seems specific to Self + @classmethod + @cache)
Activity
sterliakov commentedon May 20, 2025
Note that latest mypy does not produce
Anyand produces unboundedSelf. There's a PR for the duplicate issue, it may eventually get merged.