diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 7962429e01b0..6471e474d20a 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -672,6 +672,11 @@ def check_argument_types(self, arg_types: List[Type], arg_kinds: List[int], messages.invalid_keyword_var_arg(arg_type, context) # Get the type of an individual actual argument (for *args # and **args this is the item type, not the collection type). + if (isinstance(arg_type, TupleType) + and tuple_counter[0] >= len(arg_type.items) + and arg_kinds[actual] == nodes.ARG_STAR): + # The tuple is exhausted. Continue with further arguments. + continue actual_type = get_actual_type(arg_type, arg_kinds[actual], tuple_counter) check_arg(actual_type, arg_type, arg_kinds[actual], @@ -1667,7 +1672,8 @@ def map_actuals_to_formals(caller_kinds: List[int], map[j].append(i) else: break - j += 1 + if callee_kinds[j] != nodes.ARG_STAR: + j += 1 else: # Assume that it is an iterable (if it isn't, there will be # an error later). @@ -1676,6 +1682,8 @@ def map_actuals_to_formals(caller_kinds: List[int], break else: map[j].append(i) + if callee_kinds[j] == nodes.ARG_STAR: + break j += 1 elif kind == nodes.ARG_NAMED: name = caller_names[i] diff --git a/mypy/test/data.py b/mypy/test/data.py index 8b21db331796..22d842688d40 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -405,7 +405,7 @@ def repr_failure(self, excinfo): self.parent._prunetraceback(excinfo) excrepr = excinfo.getrepr(style='short') - return "data: {}:{}\n{}".format(self.obj.file, self.obj.line, excrepr) + return "data: {}:{}:\n{}".format(self.obj.file, self.obj.line, excrepr) class DataSuite: diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 24cc6c7556d7..9def84aab33f 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -112,6 +112,25 @@ f(*it1) f(*it2) # E: Argument 1 to "f" has incompatible type *Iterable[str]; expected "int" [builtins fixtures/for.py] +[case testCallVarargsFunctionWithIterableAndPositional] +# options: fast_parser +from typing import Iterable +it1 = None # type: Iterable[int] +def f(*x: int) -> None: pass +f(*it1, 1, 2) +f(*it1, 1, *it1, 2) +f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" +[builtins fixtures/for.py] + +[case testCallVarargsFunctionWithTupleAndPositional] +# options: fast_parser +def f(*x: int) -> None: pass +it1 = (1, 2) +f(*it1, 1, 2) +f(*it1, 1, *it1, 2) +f(*it1, '') # E: Argument 2 to "f" has incompatible type "str"; expected "int" +[builtins fixtures/for.py] + -- Calling varargs function + type inference -- -----------------------------------------