Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@
Overloaded,
PartialType,
ProperType,
StarType,
TupleType,
Type,
TypeAliasType,
Expand Down Expand Up @@ -3288,7 +3287,7 @@ def check_assignment_to_multiple_lvalues(
last_idx: int | None = None
for idx_rval, rval in enumerate(rvalue.items):
if isinstance(rval, StarExpr):
typs = get_proper_type(self.expr_checker.visit_star_expr(rval).type)
typs = get_proper_type(self.expr_checker.accept(rval.expr))
if isinstance(typs, TupleType):
rvalues.extend([TempNode(typ) for typ in typs.items])
elif self.type_is_iterable(typs) and isinstance(typs, Instance):
Expand All @@ -3311,7 +3310,7 @@ def check_assignment_to_multiple_lvalues(
iterable_end: int | None = None
for i, rval in enumerate(rvalues):
if isinstance(rval, StarExpr):
typs = get_proper_type(self.expr_checker.visit_star_expr(rval).type)
typs = get_proper_type(self.expr_checker.accept(rval.expr))
if self.type_is_iterable(typs) and isinstance(typs, Instance):
if iterable_start is None:
iterable_start = i
Expand Down Expand Up @@ -3674,8 +3673,7 @@ def check_lvalue(self, lvalue: Lvalue) -> tuple[Type | None, IndexExpr | None, V
]
lvalue_type = TupleType(types, self.named_type("builtins.tuple"))
elif isinstance(lvalue, StarExpr):
typ, _, _ = self.check_lvalue(lvalue.expr)
lvalue_type = StarType(typ) if typ else None
lvalue_type, _, _ = self.check_lvalue(lvalue.expr)
else:
lvalue_type = self.expr_checker.accept(lvalue)

Expand Down
6 changes: 3 additions & 3 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@
ParamSpecType,
PartialType,
ProperType,
StarType,
TupleType,
Type,
TypeAliasType,
Expand Down Expand Up @@ -5156,8 +5155,9 @@ def visit_typeddict_expr(self, e: TypedDictExpr) -> Type:
def visit__promote_expr(self, e: PromoteExpr) -> Type:
return e.type

def visit_star_expr(self, e: StarExpr) -> StarType:
return StarType(self.accept(e.expr))
def visit_star_expr(self, e: StarExpr) -> Type:
# TODO: should this ever be called (see e.g. mypyc visitor)?
return self.accept(e.expr)

def object_type(self) -> Instance:
"""Return instance type 'object'."""
Expand Down
4 changes: 4 additions & 0 deletions mypy/test/testpythoneval.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ def test_python_evaluation(testcase: DataDrivenTestCase, cache_dir: str) -> None
# Normalize paths so that the output is the same on Windows and Linux/macOS.
line = line.replace(test_temp_dir + os.sep, test_temp_dir + "/")
output.append(line.rstrip("\r\n"))
if returncode > 1 and not testcase.output:
# Either api.run() doesn't work well in case of a crash, or pytest interferes with it.
# Tweak output to prevent tests with empty expected output to pass in case of a crash.
output.append("!!! Mypy crashed !!!")
if returncode == 0 and not output:
# Execute the program.
proc = subprocess.run(
Expand Down
23 changes: 23 additions & 0 deletions test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -1901,3 +1901,26 @@ a[x]
_testNativeIntTypes.py:14: error: Unsupported operand types for + ("i64" and "i32")
_testNativeIntTypes.py:15: note: Revealed type is "mypy_extensions.i64"
_testNativeIntTypes.py:16: note: Revealed type is "mypy_extensions.i64"

[case testStarUnpackNestedUnderscore]
from typing import Tuple, Dict, List

def crash() -> None:
d: Dict[int, Tuple[str, int, str]] = {}
k, (v1, *_) = next(iter(d.items()))

def test1() -> None:
vs: List[str]
d: Dict[int, Tuple[str, int, int]] = {}
k, (v1, *vs) = next(iter(d.items()))
reveal_type(vs)

def test2() -> None:
d: Dict[int, Tuple[str, int, str]] = {}
k, (v1, *vs) = next(iter(d.items()))
reveal_type(vs)
[out]
_testStarUnpackNestedUnderscore.py:10: error: List item 0 has incompatible type "int"; expected "str"
_testStarUnpackNestedUnderscore.py:10: error: List item 1 has incompatible type "int"; expected "str"
_testStarUnpackNestedUnderscore.py:11: note: Revealed type is "builtins.list[builtins.str]"
_testStarUnpackNestedUnderscore.py:16: note: Revealed type is "builtins.list[builtins.object]"