mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Report an error if *args or **kwargs are passed when all other arguments are filled.

Open chriselion opened this issue 7 months ago • 4 comments

Bug Report You can pass **kwargs or *args to a function, even if all of its arguments are already passed. I would expect this to raise an error, since it's only valid for empty kwargs and args.

To Reproduce playground link

def f(x: int) -> int:
    return x + 1
    
def g(x: int, **kwargs) -> int:
    return f(x, **kwargs)
    
def h(x: int, args: list[int]) -> int:
    return f(x, *args)

g(1, bar=42)
h(2, [])
h(3, [1337])

Expected Behavior In both g and h, the x argument is specified, so I would expecting passing **kwargs or *args to produce an error, since they can never correctly pass additional arguments.

Actual Behavior

Success: no issues found in 1 source file

Your Environment I tried several versions of mypy (including 1.16.0 and master) with python3.12 in mypy playground. I tried with both with and without --check-untyped-defs

** Related Issues

  • This is a more general case of https://github.com/python/mypy/issues/13380 (that issue specifically mentions functions with no arguments)
  • https://github.com/python/mypy/issues/12206 is another issue with splatting, but I don't think it's quite the same

chriselion avatar Jun 06 '25 18:06 chriselion

Interestingly, if I add

def k(x: int, args: list[int]) -> int:
    return f(x=x, *args)

it produces an error:

main.py:11: error: "f" gets multiple values for keyword argument "x"  [misc]

(playground)

This is more-or-less the sort of error I would expect, although the wording is a bit confusing.

chriselion avatar Jun 06 '25 18:06 chriselion

This wording is almost the same as the message of the corresponding RuntimeError, so I think it's good enough.

This behavior is a bit inconsistent, though, your FR to reject calls where all args are present together with vararg sounds good! In both cases the only case when unpacking is valid is an empty arg/kwarg, so rejecting such calls would be helpful.

sterliakov avatar Jun 06 '25 22:06 sterliakov

This is related to a recent discussion in the Python typing forum.

erictraut avatar Jun 06 '25 22:06 erictraut

Thanks @erictraut, the proposed "allow any set of arguments that could potentially succeed at runtime EXCEPT if the only potential argument-to-parameter mappings involve unpacking empty arguments" approach sounds like the behavior that I expected.

chriselion avatar Jun 07 '25 00:06 chriselion