python/mypy

Too many arguments with specific argument after *args

tierriminator opened this issue · 4 comments

Bug Report

When using specific arguments after providing arguments with *args, mypy will report an error.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.11&gist=f8b653e4348ebc7a4006c2a126ed0d85

Expected Behavior

Mypy should succeed.

Actual Behavior

main.py:5: error: Too many arguments for "foo"  [call-arg]
Found 1 error in 1 file (checked 1 source file)

Your Environment

See playground

This is similar to #9710, however, mypy is not entirely incorrect. This simple example would "type check" but blow up at runtime if Tuple was compatible with foo's signature :

def foo(x: int, y: int, z: int):
    pass

def bar(*a: int):
    foo(*a, 0)

bar(1, 2, 3)  # => foo(1, 2, 3, 0) => too many arguments!

I suppose this goes the other way too. bar() is a valid way to call bar but it would immediately blow up as foo would only get one argument.

The error message should probably be tweaked to say Potentially too few or many arguments for "foo" or something similar.

The issue I have with this is that mypy won't complain if we just omit the specific argument or use it at the beginning.
Both

def foo(x: int, y: int, z: int):
    pass

def bar(*a: int):
    foo(*a)

and

def foo(x: int, y: int, z: int):
    pass

def bar(*a: int):
    foo(0, *a)

will type check successfully.
In both cases we would have the same problem of potentially incorrect number of arguments.

Yea, I don't know what's up with that. I'd guess that is either an oversight or an explicit design choice to avoid technically-correct-but-low-value-relative-to-noise type errors.

Almost equally simple reduced example (playground):

def SomeFun(a, b):
    pass

SomeFun(*[1], 2)
main.py:4: error: Too many arguments for "SomeFun"  [call-arg]
Found 1 error in 1 file (checked 1 source file)