python / python/mypy

Overloaded class methods not supported by Protocol

Open
#16,584 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug topic-overloads topic-protocols
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Bug Report

If a Protocol contains a class method, a class (or an object of this class) won't fulfill the Protocol if the class method is overloaded.

To Reproduce

from typing import Protocol, overload


class SupportsFooOnClass(Protocol):
    @classmethod
    def foo(cls, x: int) -> str: ...


class Fooer:
    @overload
    @classmethod
    def foo(cls, x: int) -> str:
        ...
        
    @overload
    @classmethod
    def foo(cls, x: float) -> complex:
        ...
        
    @classmethod
    def foo(cls, x: int | float) -> str | complex:
        if isinstance(x, int):
            return "foo"
        return 5j
        

def use_foo(fooable: SupportsFooOnClass):
    pass


use_foo(Fooer())
use_foo(Fooer)

https://mypy-play.net/?mypy=latest&python=3.10&gist=eb4e527b43fb5b249b7afeadd5aa853d

Expected Behavior

Success.
Class Fooer supports a class method foo with one argument of type int and return type of str.
The same code passes pyright's check.

Actual Behavior

main.py:31: error: Argument 1 to "use_foo" has incompatible type "Fooer"; expected "SupportsFooOnClass"  [arg-type]
main.py:31: note: Protocol member SupportsFooOnClass.foo expected class or static method
main.py:32: error: Argument 1 to "use_foo" has incompatible type "type[Fooer]"; expected "SupportsFooOnClass"  [arg-type]
main.py:32: note: Protocol member SupportsFooOnClass.foo expected class or static method
Found 2 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.7.1
  • Mypy command-line flags: -
  • Mypy configuration options from mypy.ini (and other config files): -
  • Python version used: 3.10

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the minimal Python reproduction from the issue and compare mypy's handling of the Protocol, overloaded class method, and direct class or instance calls. Trace the Protocol compatibility check and overload handling, then verify that both use_foo(Fooer()) and use_foo(Fooer) pass without errors while preserving the existing overload behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.