diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 135f796d479e..25db339d63dc 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1233,7 +1233,9 @@ def check_for_extra_actual_arguments(self, for i, kind in enumerate(actual_kinds): if i not in all_actuals and ( kind != nodes.ARG_STAR or - not is_empty_tuple(actual_types[i])): + # We accept the other iterables than tuple (including Any) + # as star arguments because they could be empty, resulting no arguments. + is_non_empty_tuple(actual_types[i])): # Extra actual: not matched by a formal argument. ok = False if kind != nodes.ARG_NAMED: @@ -3833,9 +3835,9 @@ def is_async_def(t: Type) -> bool: return isinstance(t, Instance) and t.type.fullname() == 'typing.Coroutine' -def is_empty_tuple(t: Type) -> bool: +def is_non_empty_tuple(t: Type) -> bool: t = get_proper_type(t) - return isinstance(t, TupleType) and not t.items + return isinstance(t, TupleType) and bool(t.items) def is_duplicate_mapping(mapping: List[int], actual_kinds: List[int]) -> bool: diff --git a/test-data/unit/check-varargs.test b/test-data/unit/check-varargs.test index ceca1fe57c94..78de84173ae4 100644 --- a/test-data/unit/check-varargs.test +++ b/test-data/unit/check-varargs.test @@ -353,7 +353,7 @@ class CC(C): pass from typing import Any d, a = None, None # type: (Any, A) f(a, a, *d) # Fail -f(a, *d) # Fail +f(a, *d) # Ok f(*d) # Ok g(*d) @@ -366,7 +366,6 @@ class A: pass [builtins fixtures/list.pyi] [out] main:3: error: Too many arguments for "f" -main:4: error: Too many arguments for "f" [case testListVarArgsAndSubtyping] from typing import List @@ -448,6 +447,21 @@ def f(x: int, *, y: str) -> None: pass f(y='x', *(1,)) [builtins fixtures/list.pyi] +[case testVarArgsEmptyList] +from typing import List + +def foo() -> None: + pass + +lst: List[int] = [] +foo(*lst) +[builtins fixtures/list.pyi] + +[case testVarArgsEmptyTuple] +def foo() -> None: + pass + +foo(*()) -- Overloads + varargs -- -------------------