diff --git a/mypy/checker.py b/mypy/checker.py index 431d2d38aabe..4f2de7f894b9 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1566,12 +1566,14 @@ def check_lvalue(self, lvalue: Lvalue) -> Tuple[Type, IndexExpr, Var]: elif isinstance(lvalue, IndexExpr): index_lvalue = lvalue elif isinstance(lvalue, MemberExpr): - lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, - True) + lvalue_type = self.expr_checker.analyze_ordinary_member_access(lvalue, True) self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, NameExpr): lvalue_type = self.expr_checker.analyze_ref_expr(lvalue, lvalue=True) - self.store_type(lvalue, lvalue_type) + if lvalue.name == '_': + lvalue_type = AnyType() + else: + self.store_type(lvalue, lvalue_type) elif isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr): types = [self.check_lvalue(sub_expr)[0] for sub_expr in lvalue.items] lvalue_type = TupleType(types, self.named_type('builtins.tuple')) diff --git a/mypy/semanal.py b/mypy/semanal.py index 8f285c135242..afe395ff5cfa 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -3294,7 +3294,8 @@ def name_not_defined(self, name: str, ctx: Context) -> None: self.fail(message, ctx) def name_already_defined(self, name: str, ctx: Context) -> None: - self.fail("Name '{}' already defined".format(name), ctx) + if name != '_': + self.fail("Name '{}' already defined".format(name), ctx) def fail(self, msg: str, ctx: Context, serious: bool = False, *, blocker: bool = False) -> None: diff --git a/test-data/unit/check-basic.test b/test-data/unit/check-basic.test index 05fa1a954cc2..9c7b63dfe80f 100644 --- a/test-data/unit/check-basic.test +++ b/test-data/unit/check-basic.test @@ -261,6 +261,26 @@ main:3: error: Incompatible types in assignment (expression has type "B", variab main:7: error: Incompatible types in assignment (expression has type "A", variable has type "B") main:9: error: Incompatible types in assignment (expression has type "B", variable has type "A") +[case testUnderscoreVariableIsFresh] +from typing import Tuple +_ = 1 +_ = "" +_ = "" # type: int +(_, _) = ("", 1.0 + "") # E: Unsupported left operand type for + ("float") +(_, _) = (1.0, "") +for (_, _) in ((1, "a"), (2, "b")): pass +(None for (_, _) in ((1, "a"), (2, "b"))) + +class A: + def __enter__(self) -> Tuple[int, str]: ... + def __exit__(self, *_) -> None: ... + +with A() as (_, _): pass + +def f(_: int) -> None: + _ = "" + _, _ = (1.0, b"") + [case testGlobalDefinedInBlockWithType] class A: pass