diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py index 9c615f857731a..5f149713cd39c 100644 --- a/mypy/plugins/dataclasses.py +++ b/mypy/plugins/dataclasses.py @@ -460,16 +460,18 @@ def _collect_field_args(expr: Expression, ): # field() only takes keyword arguments. args = {} - for name, arg in zip(expr.arg_names, expr.args): - if name is None: - # This means that `field` is used with `**` unpacking, - # the best we can do for now is not to fail. - # TODO: we can infer what's inside `**` and try to collect it. - ctx.api.fail( - 'Unpacking **kwargs in "field()" is not supported', - expr, - ) + for name, arg, kind in zip(expr.arg_names, expr.args, expr.arg_kinds): + if not kind.is_named(): + if kind.is_named(star=True): + # This means that `field` is used with `**` unpacking, + # the best we can do for now is not to fail. + # TODO: we can infer what's inside `**` and try to collect it. + message = 'Unpacking **kwargs in "field()" is not supported' + else: + message = '"field()" does not accept positional arguments' + ctx.api.fail(message, expr) return True, {} + assert name is not None args[name] = arg return True, args return False, {} diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test index 57ed2813c54bf..2e5e1cfd53838 100644 --- a/test-data/unit/check-dataclasses.test +++ b/test-data/unit/check-dataclasses.test @@ -1320,6 +1320,19 @@ main:7: note: def [_T] field(*, default_factory: Callable[[], _T], init: boo main:7: note: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any [builtins fixtures/dataclasses.pyi] +[case testDataclassFieldWithPositionalArguments] +# flags: --python-version 3.7 +from dataclasses import dataclass, field + +@dataclass +class C: + x: int = field(0) # E: "field()" does not accept positional arguments \ + # E: No overload variant of "field" matches argument type "int" \ + # N: Possible overload variants: \ + # N: def [_T] field(*, default: _T, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> _T \ + # N: 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 \ + # N: def field(*, init: bool = ..., repr: bool = ..., hash: Optional[bool] = ..., compare: bool = ..., metadata: Optional[Mapping[str, Any]] = ..., kw_only: bool = ...) -> Any +[builtins fixtures/dataclasses.pyi] [case testDataclassFieldWithTypedDictUnpacking] # flags: --python-version 3.7