Skip to content

Return type is Self when calling an inherited decorated classmethod that returns Self #19023

Closed

Description

@injust

Bug Report

When calling an inherited decorated classmethod that returns Self, mypy does not resolve the type and thinks the type of the return value is Self.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.13&flags=strict&gist=664aeee2f4339ce869129dfba8017289

from __future__ import annotations

from collections.abc import Callable
from functools import wraps
from typing import Any, Self, TypeVar

type JSON = dict[str, Any]
T = TypeVar("T")


def debug(make: Callable[[type[T], JSON], T]) -> Callable[[type[T], JSON], T]:
    @wraps(make)
    def wrapper(cls: type[T], data: JSON) -> T:
        return make(cls, data)

    return wrapper


class Foo:
    data: JSON
    
    def __init__(self, data: JSON) -> None:
        self.data = data

    @classmethod
    @debug
    def make(cls, data: JSON) -> Self:
        return cls(data)


class Bar(Foo):
    pass


def test() -> Bar:
    return Bar.make({})

Expected Behavior

The code should type check.

Actual Behavior

main.py:36: error: Incompatible return value type (got "Self", expected "Bar")  [return-value]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.15.0
  • Mypy command-line flags: --strict
  • Python version used: 3.13

Activity

  1. sterliakov commented on May 4, 2025

    @sterliakov
    Collaborator

    This is almost a duplicate of #18993 - if you reveal_type(Foo.make({})), that will be Self. We leak self types from decorated classmethods somewhere.

  2. added a commit that references this issue on Jun 13, 2025
    6c3c4a7
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 wrongtopic-self-typesTypes for self

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions