Skip to content

Commit 3f7444a

Browse files
authored
New semantic analyzer: Support multiple assignments to underscore (#6450)
I also enable the existing test file with existing tests for this feature. I discovered a bug in `make_name_lvalue_var()` that caused some existing tests to fail, so I fixed it. I skip three tests (they already have issues). I also updated one test case because the behavior is more consistent in new analyzer (it always shows `Cannot determine type`, while old one shows this error only at global scope).
1 parent e83f4fd commit 3f7444a

File tree

3 files changed

+18
-9
lines changed

3 files changed

+18
-9
lines changed

mypy/newsemanal/semanal.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,8 +1937,9 @@ def analyze_typeddict_assign(self, s: AssignmentStmt) -> bool:
19371937
# type checker will try to infer Any for the l.h.s.
19381938
# Remove this after new analyzer is the default one!
19391939
lvalue.fullname = self.qualified_name(name)
1940-
lvalue.node = self.make_name_lvalue_var(lvalue, self.current_symbol_kind(),
1941-
inferred=True)
1940+
lvalue.is_inferred_def = True
1941+
lvalue.kind = kind = self.current_symbol_kind()
1942+
lvalue.node = self.make_name_lvalue_var(lvalue, kind, inferred=True)
19421943
return True
19431944

19441945
def analyze_lvalues(self, s: AssignmentStmt) -> None:
@@ -2314,11 +2315,19 @@ def analyze_name_lvalue(self,
23142315
added = self.add_symbol(name, var, lvalue)
23152316
# Only bind expression if we successfully added name to symbol table.
23162317
if added:
2318+
lvalue.is_new_def = True
2319+
lvalue.is_inferred_def = True
2320+
lvalue.kind = kind
23172321
lvalue.node = var
23182322
if kind == GDEF:
23192323
lvalue.fullname = var._fullname
23202324
else:
23212325
lvalue.fullname = lvalue.name
2326+
if self.is_func_scope():
2327+
if unmangle(name) == '_':
2328+
# Special case for assignment to local named '_': always infer 'Any'.
2329+
typ = AnyType(TypeOfAny.special_form)
2330+
self.store_declared_types(lvalue, typ)
23222331
if is_final and self.is_final_redefinition(kind, name):
23232332
self.fail("Cannot redefine an existing name as final", lvalue)
23242333
else:
@@ -2377,9 +2386,6 @@ def make_name_lvalue_var(self, lvalue: NameExpr, kind: int, inferred: bool) -> V
23772386
# fullanme should never stay None
23782387
v._fullname = lvalue.name
23792388
v.is_ready = False # Type not inferred yet
2380-
lvalue.is_new_def = True
2381-
lvalue.is_inferred_def = True
2382-
lvalue.kind = kind
23832389
return v
23842390

23852391
def make_name_lvalue_point_to_existing_def(

mypy/test/hacks.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
'check-incomplete-fixture.test',
2525
'check-incremental.test',
2626
'check-inference-context.test',
27-
'check-inference.test',
2827
'check-isinstance.test',
2928
'check-literal.test',
3029
'check-modules.test',

test-data/unit/check-inference.test

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,14 +432,16 @@ def id(x: T) -> T:
432432
[out]
433433

434434
[case testUnderspecifiedInferenceResult]
435+
# flags: --new-semantic-analyzer --no-strict-optional
435436
from typing import TypeVar
436437
T = TypeVar('T')
437438
class A: pass
438439
a = None # type: A
439440

440441
def ff() -> None:
441442
x = f() # E: Need type annotation for 'x'
442-
reveal_type(x) # E: Revealed type is 'Any'
443+
reveal_type(x) # E: Revealed type is 'Any' \
444+
# E: Cannot determine type of 'x'
443445

444446
g(None) # Ok
445447
f() # Ok because not used to infer local variable type
@@ -1045,7 +1047,7 @@ class B: pass
10451047
[builtins fixtures/for.pyi]
10461048

10471049
[case testReusingInferredForIndex2]
1048-
# flags: --allow-redefinition
1050+
# flags: --allow-redefinition --no-new-semantic-analyzer
10491051

10501052
def f() -> None:
10511053
for a in [A()]: pass
@@ -1550,7 +1552,9 @@ def add():
15501552
map[1] = 2
15511553
[builtins fixtures/dict.pyi]
15521554

1555+
-- Depends on #6425
15531556
[case testSpecialCaseEmptyListInitialization]
1557+
# flags: --no-new-semantic-analyzer
15541558
def f(blocks: Any): # E: Name 'Any' is not defined
15551559
to_process = [] # E: Need type annotation for 'to_process'
15561560
to_process = list(blocks)
@@ -2455,7 +2459,7 @@ _ = 0
24552459
_ = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
24562460

24572461
[case testUnusedTargetNotClass]
2458-
# flags: --allow-redefinition
2462+
# flags: --allow-redefinition --no-new-semantic-analyzer
24592463
class C:
24602464
_, _ = 0, 0
24612465
_ = ''

0 commit comments

Comments
 (0)