python / python/mypy

Report protocol problems in no_variant_matches_arguments if possible

Open
#17,092 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
Dominant language
Python
Stars
20.6k
Forks
3.3k
PR merge metrics
PR metrics pending

Description

Feature

Report protocol problems in no_variant_matches_arguments if possible.

Pitch

Given following example:

from typing import Protocol, overload


class Foo(Protocol):
    def some_method(self, value: int = 0) -> None: ...


class Bar:
    def some_method(self, value: int) -> None:
        pass


@overload
def accept_foo(value: Foo, v: int) -> None:
    pass


@overload
def accept_foo(value: Foo, v: float) -> None:
    pass


def accept_foo(value: Foo, v: int | float) -> None:
    pass


accept_foo(Bar(), 1)

The Bar has conflict with the Protocol Foo, but currently Mypy won't report the protocol problems. This is the current error report:

protocol_example.py:27: error: No overload variant of "accept_foo" matches argument types "Bar", "int"  [call-overload]
protocol_example.py:27: note: Possible overload variants:
protocol_example.py:27: note:     def accept_foo(value: Foo, v: int) -> None
protocol_example.py:27: note:     def accept_foo(value: Foo, v: float) -> None
Found 1 error in 1 file (checked 1 source file)

If we can report the protocol problems in this case, it may save developers time to figure out what' wrong.

I did a proof-of-concept implementation here: https://github.com/python/mypy/commit/a2040d3680320afbac6e13b3b04593a7965242bc. This is the updated error report:

protocol_example.py:27: error: No overload variant of "accept_foo" matches argument types "Bar", "int"  [call-overload]
protocol_example.py:27: note: Following member(s) of "Bar" have conflicts:
protocol_example.py:27: note:     Expected:
protocol_example.py:27: note:         def some_method(self, value: int = ...) -> None
protocol_example.py:27: note:     Got:
protocol_example.py:27: note:         def some_method(self, value: int) -> None
protocol_example.py:27: note:     Expected:
protocol_example.py:27: note:         def some_method(self, value: int = ...) -> None
protocol_example.py:27: note:     Got:
protocol_example.py:27: note:         def some_method(self, value: int) -> None
protocol_example.py:27: note: Possible overload variants:
protocol_example.py:27: note:     def accept_foo(value: Foo, v: int) -> None
protocol_example.py:27: note:     def accept_foo(value: Foo, v: float) -> None
Found 1 error in 1 file (checked 1 source file)

If this is OK, I'd happy to refine the implementation and submit a PR.

Thanks.

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 at the no_variant_matches_arguments entry point and review the proof-of-concept commit linked in the issue. Reproduce the supplied Protocol and overload example, then verify that the diagnostic reports the conflicting members accurately without duplicate or misleading output.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers, devtools
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.