From 31768757237e27bc6db2f11edd9263d7e94145d6 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 29 Jul 2016 11:22:52 -0700 Subject: [PATCH 1/4] Fix "Too many arguments" error for f(*a, b) where f is varargs. --- mypy/checkexpr.py | 2 ++ test-data/unit/check-varargs.test | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 7962429e01b0..8dfb03ab4dfc 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1676,6 +1676,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/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index 24cc6c7556d7..cbb28b22ee8a 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -112,6 +112,16 @@ 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] + -- Calling varargs function + type inference -- ----------------------------------------- From 56171b52205ef3d0c97a6c8f698ea0c5d59bd6a5 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 29 Jul 2016 12:39:38 -0700 Subject: [PATCH 2/4] Also fix it for f(*(1, 2), 3) -- tuples are special here. --- mypy/checkexpr.py | 6 +++++- test-data/unit/check-varargs.test | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 8dfb03ab4dfc..0b70afe02e48 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -672,6 +672,9 @@ 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): + # 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 +1670,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). diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index cbb28b22ee8a..9def84aab33f 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -122,6 +122,15 @@ 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 -- ----------------------------------------- From c0deb14142cab9886e7d7e316c4cbaa42ddc30c3 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 29 Jul 2016 09:05:52 -0700 Subject: [PATCH 3/4] Add an extra colon to the "data: :" output from failing tests. @gnprice: With this small change my Emacs "compile" mode lets me jump to that line directly. --- mypy/test/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From 89190ef3353954c310ccc7b7854efa2c148aed0b Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 29 Jul 2016 13:43:01 -0700 Subject: [PATCH 4/4] Only consider the tuple exhausted if kind == ARG_STAR. --- mypy/checkexpr.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 0b70afe02e48..6471e474d20a 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -672,7 +672,9 @@ 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): + 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],