diff --git a/mypy/messages.py b/mypy/messages.py index bc750fc0955c..9922d9d16a2c 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -645,7 +645,7 @@ def incompatible_argument(self, n: int, m: int, callee: CallableType, arg_type: # For function calls with keyword arguments, display the argument name rather than the # number. arg_label = str(n) - if isinstance(context, CallExpr): + if isinstance(context, CallExpr) and len(context.arg_names) >= n: arg_name = context.arg_names[n - 1] if arg_name is not None: arg_label = '"{}"'.format(arg_name) diff --git a/mypy/server/deps.py b/mypy/server/deps.py index 9725a52929e5..b2b388e75d43 100644 --- a/mypy/server/deps.py +++ b/mypy/server/deps.py @@ -376,7 +376,8 @@ def process_lvalue(self, lvalue: Expression) -> None: elif isinstance(lvalue, TupleExpr): for item in lvalue.items: self.process_lvalue(item) - # TODO: star lvalue + elif isinstance(lvalue, StarExpr): + self.process_lvalue(lvalue.expr) def is_self_member_ref(self, memberexpr: MemberExpr) -> bool: """Does memberexpr to refer to an attribute of self?""" diff --git a/test-data/unit/deps.test b/test-data/unit/deps.test index a831cc4b1b56..db1655cac1f4 100644 --- a/test-data/unit/deps.test +++ b/test-data/unit/deps.test @@ -1109,3 +1109,20 @@ class A(B): -> -> -> m, m.D + +[case testIndexedStarLvalue] +from typing import List, Tuple + +class B: + def __setitem__(self, i: int, v: List[str]) -> None: pass + +def g() -> Tuple[int, str, str]: pass + +def f(b: B) -> None: + a, *b[0] = g() +[builtins fixtures/list.pyi] +[out] + -> m.f + -> m.f + -> , m.B, m.f + -> m.f diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 9f9bd5e4aea8..b128c238c670 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -34,6 +34,11 @@ -- -- Test runner can parse options from mypy.ini file. Updating this file in between -- incremental runs is not yet supported. +-- +-- Each test case run without caching and with caching (if the initial run passes), +-- unless it has one a --skip-cache or --skip-nocache suffix. We sometimes +-- skip caching test cases to speed up tests, if the caching variant is not useful. +-- The caching test case variants get an implicit _cached suffix. [case testReprocessFunction] import m @@ -5801,6 +5806,90 @@ class M(type): == a.py:2: error: Argument 1 to "f" of "M" has incompatible type "int"; expected "str" +[case testExtendedUnpacking-skip-cache] +from typing import List +from a import g +def f() -> List[int]: + a, *b = g() + return b + +[file a.py] +from typing import Tuple +def g() -> Tuple[str, int, int]: pass + +[file a.py.2] +from typing import Tuple +def g() -> Tuple[str, str]: pass + +[builtins fixtures/tuple.pyi] +[out] +== +main:5: error: Incompatible return value type (got "List[str]", expected "List[int]") + +[case testUnpackInExpression1-skip-cache] +from typing import Tuple, List +from a import t + +def f() -> Tuple[int, int]: + return (1, *t()) + +def g() -> List[int]: + return [1, *t()] + +[file a.py] +from typing import Tuple +def t() -> Tuple[int]: ... + +[file a.py.2] +from typing import Tuple +def t() -> Tuple[str]: ... + +[builtins fixtures/list.pyi] +[out] +== +main:5: error: Incompatible return value type (got "Tuple[int, str]", expected "Tuple[int, int]") +main:8: error: List item 1 has incompatible type "Tuple[str]"; expected "int" + +[case testUnpackInExpression2-skip-cache] +from typing import Set +from a import t + +def f() -> Set[int]: + return {1, *t()} + +[file a.py] +from typing import Tuple +def t() -> Tuple[int]: pass + +[file a.py.2] +from typing import Tuple +def t() -> Tuple[str]: pass + +[builtins fixtures/set.pyi] +[out] +== +main:5: error: Argument 2 to has incompatible type "*Tuple[str]"; expected "int" + +[case testUnpackInExpression3-skip-cache] +from typing import Dict +from a import d + +def f() -> Dict[int, str]: + return {1: '', **d()} + +[file a.py] +from typing import Dict +def d() -> Dict[int, str]: pass + +[file a.py.2] +from typing import Dict +def d() -> Dict[int, int]: pass + +[builtins fixtures/dict.pyi] +[out] +== +main:5: error: Argument 1 to "update" of "dict" has incompatible type "Dict[int, int]"; expected "Mapping[int, str]" + [case testAwaitAndAsyncDef-skip-cache] from a import g diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index e946f5e407ff..e193de93dffd 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -1259,3 +1259,14 @@ class B: [out] _testInvalidSlots.py:2: error: Incompatible types in assignment (expression has type "int", base class "object" defined the type as "Union[str, Iterable[str], None]") _testInvalidSlots.py:4: error: Incompatible types in assignment (expression has type "Tuple[int, int]", base class "object" defined the type as "Union[str, Iterable[str], None]") + +[case testDictWithStarStarSpecialCase] +from typing import Dict + +def f() -> Dict[int, str]: + return {1: '', **d()} + +def d() -> Dict[int, int]: + return {} +[out] +_testDictWithStarStarSpecialCase.py:4: error: Argument 1 to "update" of "dict" has incompatible type "Dict[int, int]"; expected "Mapping[int, str]"