python / python/mypy

Protocol incorrectly matches when positional or keyword parameter matches *args

Open
#21,014 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Bug Report

When a protocol defines a function with a keyword or positional parameter (a: int) -> None, a concrete function where said parameter is missing, but matches the *args parameter (*args: int) -> None will be seen as implementing the protocol.

I would expect (a: int) -> None to also need matching **kwargs such as (*args: int, **kwargs: int) -> None and for it to only match *args alone when specified as a positional only argument (e.g. (a: int, /) -> None)

Otherwise it cannot be called safely, pyright and ty both successfully raise errors for this case.

To Reproduce

https://mypy-play.net/?mypy=master&python=3.14&flags=strict&gist=a5f86e32e70cbc84c45a53db5426f78f

Expected Behavior

main.py:13: error: Argument 1 to "f" has incompatible type "C"; expected "P"  [arg-type]

because calling the method as foo(a=1) would fail.

Actual Behavior

mypy:

Success: no issues found in 1 source file

pyright:

Argument of type "C" cannot be assigned to parameter "o" of type "P" in function "f"
  "C" is incompatible with protocol "P"
    "foo" is an incompatible type
      Type "(*args: int) -> None" is not assignable to type "(a: int) -> None"
        Missing keyword parameter "a"  (reportArgumentType)

ty:

Argument to function `f` is incorrect: Expected `P`, found `C` (invalid-argument-type) [Ln 17, Col 3]

python:

Traceback (most recent call last):
  File "xxx.py", line 17, in <module>
    f(C())
    ~^^^^^
  File "xxx.py", line 14, in f
    o.foo(a=1)
    ~~~~~^^^^^
TypeError: C.foo() got an unexpected keyword argument 'a'

Your Environment

  • Mypy version used: 1.19.1 and master
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 1.14

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

Reproduce the linked mypy-play example using mypy master, Python 3.14, and --strict. Trace protocol compatibility handling for the shown foo signatures and compare the result with pyright and ty. Done means mypy reports the expected incompatible-protocol error while preserving the positional-only case.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.