diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 4e3be52ef60c..60659820c62e 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1601,7 +1601,7 @@ def check_call( callee, args, arg_kinds, arg_names, callable_name, object_type, context ) elif isinstance(callee, AnyType) or not self.chk.in_checked_function(): - return self.check_any_type_call(args, callee) + return self.check_any_type_call(args, arg_kinds, callee, context) elif isinstance(callee, UnionType): return self.check_union_call(callee, args, arg_kinds, arg_names, context) elif isinstance(callee, Instance): @@ -2513,10 +2513,6 @@ def check_argument_types( The check_call docstring describes some of the arguments. """ - check_arg = check_arg or self.check_arg - # Keep track of consumed tuple *arg items. - mapper = ArgTypeExpander(self.argument_infer_context()) - for arg_type, arg_kind in zip(arg_types, arg_kinds): arg_type = get_proper_type(arg_type) if arg_kind == nodes.ARG_STAR and not self.is_valid_var_arg(arg_type): @@ -2527,6 +2523,10 @@ def check_argument_types( ) self.msg.invalid_keyword_var_arg(arg_type, is_mapping, context) + check_arg = check_arg or self.check_arg + # Keep track of consumed tuple *arg items. + mapper = ArgTypeExpander(self.argument_infer_context()) + for i, actuals in enumerate(formal_to_actual): orig_callee_arg_type = get_proper_type(callee.arg_types[i]) @@ -3298,8 +3298,20 @@ def apply_generic_arguments( skip_unsatisfied=skip_unsatisfied, ) - def check_any_type_call(self, args: list[Expression], callee: Type) -> tuple[Type, Type]: - self.infer_arg_types_in_empty_context(args) + def check_any_type_call( + self, args: list[Expression], arg_kinds: list[ArgKind], callee: Type, context: Context + ) -> tuple[Type, Type]: + arg_types = self.infer_arg_types_in_empty_context(args) + for arg_type, arg_kind in zip(arg_types, arg_kinds): + arg_type = get_proper_type(arg_type) + if arg_kind == nodes.ARG_STAR and not self.is_valid_var_arg(arg_type): + self.msg.invalid_var_arg(arg_type, context) + if arg_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(arg_type): + is_mapping = is_subtype( + arg_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem") + ) + self.msg.invalid_keyword_var_arg(arg_type, is_mapping, context) + callee = get_proper_type(callee) if isinstance(callee, AnyType): return ( diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8c359deb4f2f..30eee955f50e 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -7688,7 +7688,7 @@ class A(thing=5): pass [out] main:1: error: Unexpected keyword argument "thing" for "__init_subclass__" of "object" -tmp/builtins.pyi:5: note: "__init_subclass__" of "object" defined here +tmp/builtins.pyi:6: note: "__init_subclass__" of "object" defined here [builtins fixtures/object_with_init_subclass.pyi] [case testInitSubclassWithImports] diff --git a/test-data/unit/check-kwargs.test b/test-data/unit/check-kwargs.test index 689553445e9d..bc87cb9c174b 100644 --- a/test-data/unit/check-kwargs.test +++ b/test-data/unit/check-kwargs.test @@ -361,6 +361,9 @@ f(**kwargs) # E: Argument after ** must be a mapping, not "Optional[Any]" def g(a: int) -> None: pass g(a=1, **4) # E: Argument after ** must be a mapping, not "int" + +def main(f: Any) -> None: + f(**3) # E: Argument after ** must be a mapping, not "int" [builtins fixtures/dict.pyi] [case testPassingKeywordVarArgsToNonVarArgsFunction] diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 3b80b9e8829a..1a4989dce223 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -276,6 +276,8 @@ f(a, *(b, cc)) [builtins fixtures/tuple.pyi] [case testInvalidVarArg] +from typing import Any + def f(a: 'A') -> None: pass @@ -289,6 +291,10 @@ f(*(a,)) f(*4) # E: Expected iterable as variadic argument f(a, *4) # E: Expected iterable as variadic argument + +def main(f: Any) -> None: + f(*3) # E: Expected iterable as variadic argument + [builtins fixtures/tuple.pyi] diff --git a/test-data/unit/fixtures/object_with_init_subclass.pyi b/test-data/unit/fixtures/object_with_init_subclass.pyi index da062349a204..5e1fdf903294 100644 --- a/test-data/unit/fixtures/object_with_init_subclass.pyi +++ b/test-data/unit/fixtures/object_with_init_subclass.pyi @@ -1,3 +1,4 @@ +import _typeshed from typing import Sequence, Iterator, TypeVar, Mapping, Iterable, Optional, Union, overload, Tuple, Generic, List class object: