Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand All @@ -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])

Expand Down Expand Up @@ -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):
Copy link
Collaborator

@sterliakov sterliakov Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe extract this into a helper? This loop is identical to one around L2516. Probably not a big deal, but would be saner

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 (
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
3 changes: 3 additions & 0 deletions test-data/unit/check-kwargs.test
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 6 additions & 0 deletions test-data/unit/check-varargs.test
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ f(a, *(b, cc))
[builtins fixtures/tuple.pyi]

[case testInvalidVarArg]
from typing import Any

def f(a: 'A') -> None:
pass

Expand All @@ -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]


Expand Down
1 change: 1 addition & 0 deletions test-data/unit/fixtures/object_with_init_subclass.pyi
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _typeshed
from typing import Sequence, Iterator, TypeVar, Mapping, Iterable, Optional, Union, overload, Tuple, Generic, List

class object:
Expand Down