diff --git a/mypy/argmap.py b/mypy/argmap.py index 7ed4681c5c92..dc78043ba01f 100644 --- a/mypy/argmap.py +++ b/mypy/argmap.py @@ -89,12 +89,17 @@ def map_actuals_to_formals(actual_kinds: List[nodes.ArgKind], # # TODO: If there are also tuple varargs, we might be missing some potential # matches if the tuple was short enough to not match everything. - unmatched_formals = [fi for fi in range(nformals) - if (formal_names[fi] - and (not formal_to_actual[fi] - or actual_kinds[formal_to_actual[fi][0]] == nodes.ARG_STAR) - and formal_kinds[fi] != nodes.ARG_STAR) - or formal_kinds[fi] == nodes.ARG_STAR2] + unmatched_formals = [] + for fi in range(nformals): + if (formal_names[fi] + and formal_kinds[fi] != nodes.ARG_STAR + and (not formal_to_actual[fi] + or actual_kinds[formal_to_actual[fi][0]] == nodes.ARG_STAR) + # Arguments with default values should not be matched: + and not formal_kinds[fi].is_optional() + or formal_kinds[fi] == nodes.ARG_STAR2): + unmatched_formals.append(fi) + for ai in ambiguous_actual_kwargs: for fi in unmatched_formals: formal_to_actual[fi].append(ai) diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index e022923ef1e4..642721c1b073 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -96,7 +96,7 @@ 'check-functools.test', 'check-singledispatch.test', 'check-slots.test', - 'check-formatting.test' + 'check-formatting.test', ] # Tests that use Python 3.8-only AST features (like expression-scoped ignores): diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 73476a646c99..611359c56d0e 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1346,14 +1346,7 @@ from dataclasses import dataclass, field @dataclass class Foo: - bar: float = field(**{"repr": False}) -[out] -main:7: error: Unpacking **kwargs in "field()" is not supported -main:7: error: No overload variant of "field" matches argument type "Dict[str, bool]" -main:7: note: Possible overload variants: -main:7: note: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T -main:7: note: def [_T] field(*, default_factory: Callable[[], _T], init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T -main:7: note: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any + bar: float = field(**{"repr": False}) # E: Unpacking **kwargs in "field()" is not supported [builtins fixtures/dataclasses.pyi] [case testDataclassFieldWithPositionalArguments] diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 7f0b8af3ba0e..d1bde535c65d 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -484,13 +484,50 @@ def f(*vargs: int, **kwargs: object) -> None: def g(arg: int = 0, **kwargs: object) -> None: pass +def h(*, arg: int = 0, **kwargs: object) -> None: + pass + +def j(arg: int, **kwargs: object) -> None: + pass + +def k(*, arg: int, **kwargs: object) -> None: + pass + d = {} # type: Dict[str, object] +f() f(**d) -g(**d) # E: Argument 1 to "g" has incompatible type "**Dict[str, object]"; expected "int" +g() +g(**d) +g(1, **d) +g(arg=1, **d) +h() +h(**d) +h(arg=1, **d) +j(1) +j(1, **d) +j(arg=1, **d) +j(**d) # E: Argument 1 to "j" has incompatible type "**Dict[str, object]"; expected "int" +k(arg=1) +k(arg=1, **d) +k(**d) # E: Argument 1 to "k" has incompatible type "**Dict[str, object]"; expected "int" m = {} # type: Mapping[str, object] +f() f(**m) -g(**m) # E: Argument 1 to "g" has incompatible type "**Mapping[str, object]"; expected "int" +g() +g(**m) +g(1, **d) +g(arg=1, **d) +h() +h(**m) +h(arg=1, **d) +j(1) +j(1, **d) +j(arg=1, **d) +j(**m) # E: Argument 1 to "j" has incompatible type "**Mapping[str, object]"; expected "int" +k(arg=1) +k(arg=1, **d) +k(**m) # E: Argument 1 to "k" has incompatible type "**Mapping[str, object]"; expected "int" [builtins fixtures/dict.pyi] [case testPassingEmptyDictWithStars]