Skip to content

Commit 694dc09

Browse files
authored
Fix "Too many arguments" error for f(*a, b) where f is varargs. (#1964)
Fixes #1892 (all cases). Also fixes #1800.
1 parent 38bbe61 commit 694dc09

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

mypy/checkexpr.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ def check_argument_types(self, arg_types: List[Type], arg_kinds: List[int],
672672
messages.invalid_keyword_var_arg(arg_type, context)
673673
# Get the type of an individual actual argument (for *args
674674
# and **args this is the item type, not the collection type).
675+
if (isinstance(arg_type, TupleType)
676+
and tuple_counter[0] >= len(arg_type.items)
677+
and arg_kinds[actual] == nodes.ARG_STAR):
678+
# The tuple is exhausted. Continue with further arguments.
679+
continue
675680
actual_type = get_actual_type(arg_type, arg_kinds[actual],
676681
tuple_counter)
677682
check_arg(actual_type, arg_type, arg_kinds[actual],
@@ -1667,7 +1672,8 @@ def map_actuals_to_formals(caller_kinds: List[int],
16671672
map[j].append(i)
16681673
else:
16691674
break
1670-
j += 1
1675+
if callee_kinds[j] != nodes.ARG_STAR:
1676+
j += 1
16711677
else:
16721678
# Assume that it is an iterable (if it isn't, there will be
16731679
# an error later).
@@ -1676,6 +1682,8 @@ def map_actuals_to_formals(caller_kinds: List[int],
16761682
break
16771683
else:
16781684
map[j].append(i)
1685+
if callee_kinds[j] == nodes.ARG_STAR:
1686+
break
16791687
j += 1
16801688
elif kind == nodes.ARG_NAMED:
16811689
name = caller_names[i]

test-data/unit/check-varargs.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,25 @@ f(*it1)
112112
f(*it2) # E: Argument 1 to "f" has incompatible type *Iterable[str]; expected "int"
113113
[builtins fixtures/for.py]
114114

115+
[case testCallVarargsFunctionWithIterableAndPositional]
116+
# options: fast_parser
117+
from typing import Iterable
118+
it1 = None # type: Iterable[int]
119+
def f(*x: int) -> None: pass
120+
f(*it1, 1, 2)
121+
f(*it1, 1, *it1, 2)
122+
f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int"
123+
[builtins fixtures/for.py]
124+
125+
[case testCallVarargsFunctionWithTupleAndPositional]
126+
# options: fast_parser
127+
def f(*x: int) -> None: pass
128+
it1 = (1, 2)
129+
f(*it1, 1, 2)
130+
f(*it1, 1, *it1, 2)
131+
f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int"
132+
[builtins fixtures/for.py]
133+
115134

116135
-- Calling varargs function + type inference
117136
-- -----------------------------------------

0 commit comments

Comments
 (0)