python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.5k stars 2.83k forks source link

Errors for incorrect type on `**kwargs` should give the name of the argument #16490

Open tusharsadhwani opened 1 year ago

tusharsadhwani commented 1 year ago

Bug Report

In case of **kwargs being passed to an overloaded function, one issue gets raised for every overload of that function. This problem is not present when passing a regular incompatible type to that overloaded function, eg. int

To Reproduce

import json
from typing import Any

def load(data: str, **kwargs: object) -> Any:
    return json.loads(data, **kwargs)

Gist: https://mypy-play.net/?mypy=master&python=3.11&gist=8d7f8bb50c5f9022469b59ec127df614

The bug won't reproduce for eg. if **kwargs: object was replaced with x: object.

Expected Behavior

Single issue being raised.

Actual Behavior

$ mypy asd.py
asd.py:5: error: Argument 2 to "loads" has incompatible type "**dict[str, object]"; expected "type[JSONDecoder] | None"  [arg-type]
asd.py:5: error: Argument 2 to "loads" has incompatible type "**dict[str, object]"; expected "Callable[[dict[Any, Any]], Any] | None"  [arg-type]
asd.py:5: error: Argument 2 to "loads" has incompatible type "**dict[str, object]"; expected "Callable[[str], Any] | None"  [arg-type]
asd.py:5: error: Argument 2 to "loads" has incompatible type "**dict[str, object]"; expected "Callable[[list[tuple[Any, Any]]], Any] | None"  [arg-type]
Found 4 errors in 1 file (checked 1 source file)
erictraut commented 1 year ago

The error isn't repeated for each overload. It's repeated for each required parameter in the selected overload. This is consistent with non-overloaded functions and normal keyword parameters.

def func(x: str, y: int, z: complex):
    pass

func(1, "", "") # Three errors emitted, one for each parameter

I think mypy's doing the right thing here. Pyright's behavior is the same, FWIW.

tusharsadhwani commented 1 year ago

Ah, I see. The Argument 2 of "loads" bit confused me. I thought it's talking about the same parameter.

JelleZijlstra commented 1 year ago

Re-opening as a usability issue to improve the error messages here, as I agree the "argument 2 to loads" wording is confusing. For comparison, pyright says this: Argument of type "object" cannot be assigned to parameter "cls" of type "type[JSONDecoder] | None" in function "loads" (and the same for the other parameters).

I think we should also give the name of the argument where there is a type mismatch instead of just saying "argument 2", though obviously we don't need to match pyright's error exactly.

tusharsadhwani commented 1 year ago

That is indeed much better, I'd like to work on this issue then.