Skip to content

Commit c00f82f

Browse files
authored
Always complain about invalid varargs and varkwargs (#18207)
1 parent 70eab9a commit c00f82f

File tree

5 files changed

+27
-18
lines changed

5 files changed

+27
-18
lines changed

mypy/checkexpr.py

+11-9
Original file line numberDiff line numberDiff line change
@@ -2481,6 +2481,17 @@ def check_argument_types(
24812481
check_arg = check_arg or self.check_arg
24822482
# Keep track of consumed tuple *arg items.
24832483
mapper = ArgTypeExpander(self.argument_infer_context())
2484+
2485+
for arg_type, arg_kind in zip(arg_types, arg_kinds):
2486+
arg_type = get_proper_type(arg_type)
2487+
if arg_kind == nodes.ARG_STAR and not self.is_valid_var_arg(arg_type):
2488+
self.msg.invalid_var_arg(arg_type, context)
2489+
if arg_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(arg_type):
2490+
is_mapping = is_subtype(
2491+
arg_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
2492+
)
2493+
self.msg.invalid_keyword_var_arg(arg_type, is_mapping, context)
2494+
24842495
for i, actuals in enumerate(formal_to_actual):
24852496
orig_callee_arg_type = get_proper_type(callee.arg_types[i])
24862497

@@ -2573,15 +2584,6 @@ def check_argument_types(
25732584
if actual_type is None:
25742585
continue # Some kind of error was already reported.
25752586
# Check that a *arg is valid as varargs.
2576-
if actual_kind == nodes.ARG_STAR and not self.is_valid_var_arg(actual_type):
2577-
self.msg.invalid_var_arg(actual_type, context)
2578-
if actual_kind == nodes.ARG_STAR2 and not self.is_valid_keyword_var_arg(
2579-
actual_type
2580-
):
2581-
is_mapping = is_subtype(
2582-
actual_type, self.chk.named_type("_typeshed.SupportsKeysAndGetItem")
2583-
)
2584-
self.msg.invalid_keyword_var_arg(actual_type, is_mapping, context)
25852587
expanded_actual = mapper.expand_actual_type(
25862588
actual_type,
25872589
actual_kind,

mypy/messages.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1394,7 +1394,7 @@ def could_not_infer_type_arguments(
13941394
self.fail("Cannot infer function type argument", context)
13951395

13961396
def invalid_var_arg(self, typ: Type, context: Context) -> None:
1397-
self.fail("List or tuple expected as variadic arguments", context)
1397+
self.fail("Expected iterable as variadic argument", context)
13981398

13991399
def invalid_keyword_var_arg(self, typ: Type, is_mapping: bool, context: Context) -> None:
14001400
typ = get_proper_type(typ)

test-data/unit/check-functools.test

+3-1
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,16 @@ def bar(*a: bytes, **k: int):
215215
p1("a", d="a", **k)
216216
p1("a", **k) # E: Argument 2 to "foo" has incompatible type "**Dict[str, int]"; expected "str"
217217
p1(**k) # E: Argument 1 to "foo" has incompatible type "**Dict[str, int]"; expected "str"
218-
p1(*a) # E: List or tuple expected as variadic arguments
218+
p1(*a) # E: Expected iterable as variadic argument
219219

220220

221221
def baz(a: int, b: int) -> int: ...
222222
def test_baz(xs: List[int]):
223223
p3 = functools.partial(baz, *xs)
224224
p3()
225225
p3(1) # E: Too many arguments for "baz"
226+
227+
226228
[builtins fixtures/dict.pyi]
227229

228230
[case testFunctoolsPartialGeneric]

test-data/unit/check-kwargs.test

+3
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,9 @@ f(**d) # E: Keywords must be strings
358358
f(**A()) # E: Argument after ** must be a mapping, not "A"
359359
kwargs: Optional[Any]
360360
f(**kwargs) # E: Argument after ** must be a mapping, not "Optional[Any]"
361+
362+
def g(a: int) -> None: pass
363+
g(a=1, **4) # E: Argument after ** must be a mapping, not "int"
361364
[builtins fixtures/dict.pyi]
362365

363366
[case testPassingKeywordVarArgsToNonVarArgsFunction]

test-data/unit/check-varargs.test

+9-7
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,19 @@ f(a, *(b, cc))
268268
[builtins fixtures/tuple.pyi]
269269

270270
[case testInvalidVarArg]
271-
# flags: --no-strict-optional
272271
def f(a: 'A') -> None:
273272
pass
274273

275274
class A: pass
276275

277-
a = None # type: A
276+
a = A()
278277

279-
f(*None)
280-
f(*a) # E: List or tuple expected as variadic arguments
278+
f(*None) # E: Expected iterable as variadic argument
279+
f(*a) # E: Expected iterable as variadic argument
281280
f(*(a,))
281+
282+
f(*4) # E: Expected iterable as variadic argument
283+
f(a, *4) # E: Expected iterable as variadic argument
282284
[builtins fixtures/tuple.pyi]
283285

284286

@@ -543,9 +545,9 @@ if int():
543545
if int():
544546
b, b = f(b, b, *aa) # E: Argument 3 to "f" has incompatible type "*List[A]"; expected "B"
545547
if int():
546-
a, b = f(a, *a) # E: List or tuple expected as variadic arguments
548+
a, b = f(a, *a) # E: Expected iterable as variadic argument
547549
if int():
548-
a, b = f(*a) # E: List or tuple expected as variadic arguments
550+
a, b = f(*a) # E: Expected iterable as variadic argument
549551

550552
if int():
551553
a, a = f(*aa)
@@ -737,7 +739,7 @@ bar(*good1)
737739
bar(*good2)
738740
bar(*good3)
739741
bar(*bad1) # E: Argument 1 to "bar" has incompatible type "*I[str]"; expected "float"
740-
bar(*bad2) # E: List or tuple expected as variadic arguments
742+
bar(*bad2) # E: Expected iterable as variadic argument
741743
[builtins fixtures/dict.pyi]
742744

743745
-- Keyword arguments unpacking

0 commit comments

Comments
 (0)