Skip to content

@cache breaks type checking when used with @classmethod and typing.Self #19117

Closed as duplicate

Description

@divya-e47

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

from functools import cache
from typing import Self

class MyProvider:
    @classmethod
    @cache
    def get_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)

class MyProvider:
    @classmethod
    def get_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)

class MyProvider:
    @classmethod
    @cache
    def get_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

  1. sterliakov commented on May 20, 2025

    @sterliakov
    Collaborator

    Note that latest mypy does not produce Any and produces unbounded Self. There's a PR for the duplicate issue, it may eventually get merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions