Skip to content

Commit 8e385f0

Browse files
committed
Merge branch 'master' into fix-isinstance-tuple
2 parents 6e85c32 + 6dc65f6 commit 8e385f0

File tree

4 files changed

+47
-48
lines changed

4 files changed

+47
-48
lines changed

mypy/binder.py

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
from mypy.join import join_simple
99
from mypy.sametypes import is_same_type
1010

11+
from mypy.nodes import IndexExpr, MemberExpr, NameExpr
12+
13+
14+
BindableTypes = (IndexExpr, MemberExpr, NameExpr)
15+
BindableExpression = Union[IndexExpr, MemberExpr, NameExpr]
16+
1117

1218
class Frame(Dict[Key, Type]):
1319
"""A Frame represents a specific point in the execution of a program.
@@ -92,7 +98,7 @@ def push_frame(self) -> Frame:
9298
self.options_on_return.append([])
9399
return f
94100

95-
def _push(self, key: Key, type: Type, index: int=-1) -> None:
101+
def _put(self, key: Key, type: Type, index: int=-1) -> None:
96102
self.frames[index][key] = type
97103

98104
def _get(self, key: Key, index: int=-1) -> Type:
@@ -103,19 +109,23 @@ def _get(self, key: Key, index: int=-1) -> Type:
103109
return self.frames[i][key]
104110
return None
105111

106-
def push(self, node: Node, typ: Type) -> None:
107-
if not node.literal:
112+
def put(self, expr: Expression, typ: Type) -> None:
113+
# TODO: replace with isinstance(expr, BindableTypes)
114+
if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)):
108115
return
109-
key = node.literal_hash
116+
if not expr.literal:
117+
return
118+
key = expr.literal_hash
110119
if key not in self.declarations:
111-
self.declarations[key] = self.get_declaration(node)
120+
assert isinstance(expr, BindableTypes)
121+
self.declarations[key] = get_declaration(expr)
112122
self._add_dependencies(key)
113-
self._push(key, typ)
123+
self._put(key, typ)
114124

115125
def unreachable(self) -> None:
116126
self.frames[-1].unreachable = True
117127

118-
def get(self, expr: Union[Expression, Var]) -> Type:
128+
def get(self, expr: Expression) -> Type:
119129
return self._get(expr.literal_hash)
120130

121131
def is_unreachable(self) -> bool:
@@ -163,7 +173,7 @@ def update_from_options(self, frames: List[Frame]) -> bool:
163173
for other in resulting_values[1:]:
164174
type = join_simple(self.declarations[key], type, other)
165175
if not is_same_type(type, current_value):
166-
self._push(key, type)
176+
self._put(key, type)
167177
changed = True
168178

169179
self.frames[-1].unreachable = not frames
@@ -189,19 +199,13 @@ def pop_frame(self, can_skip: bool, fall_through: int) -> Frame:
189199

190200
return result
191201

192-
def get_declaration(self, expr: Node) -> Type:
193-
if isinstance(expr, RefExpr) and isinstance(expr.node, Var):
194-
type = expr.node.type
195-
if isinstance(type, PartialType):
196-
return None
197-
return type
198-
else:
199-
return None
200-
201202
def assign_type(self, expr: Expression,
202203
type: Type,
203204
declared_type: Type,
204205
restrict_any: bool = False) -> None:
206+
# TODO: replace with isinstance(expr, BindableTypes)
207+
if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)):
208+
return None
205209
if not expr.literal:
206210
return
207211
self.invalidate_dependencies(expr)
@@ -226,16 +230,16 @@ def assign_type(self, expr: Expression,
226230
and not restrict_any):
227231
pass
228232
elif isinstance(type, AnyType):
229-
self.push(expr, declared_type)
233+
self.put(expr, declared_type)
230234
else:
231-
self.push(expr, type)
235+
self.put(expr, type)
232236

233237
for i in self.try_frames:
234238
# XXX This should probably not copy the entire frame, but
235239
# just copy this variable into a single stored frame.
236240
self.allow_jump(i)
237241

238-
def invalidate_dependencies(self, expr: Expression) -> None:
242+
def invalidate_dependencies(self, expr: BindableExpression) -> None:
239243
"""Invalidate knowledge of types that include expr, but not expr itself.
240244
241245
For example, when expr is foo.bar, invalidate foo.bar.baz.
@@ -246,11 +250,11 @@ def invalidate_dependencies(self, expr: Expression) -> None:
246250
for dep in self.dependencies.get(expr.literal_hash, set()):
247251
self._cleanse_key(dep)
248252

249-
def most_recent_enclosing_type(self, expr: Expression, type: Type) -> Type:
253+
def most_recent_enclosing_type(self, expr: BindableExpression, type: Type) -> Type:
250254
if isinstance(type, AnyType):
251-
return self.get_declaration(expr)
255+
return get_declaration(expr)
252256
key = expr.literal_hash
253-
enclosers = ([self.get_declaration(expr)] +
257+
enclosers = ([get_declaration(expr)] +
254258
[f[key] for f in self.frames
255259
if key in f and is_subtype(type, f[key])])
256260
return enclosers[-1]
@@ -334,3 +338,11 @@ def top_frame_context(self) -> Iterator[Frame]:
334338
assert len(self.frames) == 1
335339
yield self.push_frame()
336340
self.pop_frame(True, 0)
341+
342+
343+
def get_declaration(expr: BindableExpression) -> Type:
344+
if isinstance(expr, RefExpr) and isinstance(expr.node, Var):
345+
type = expr.node.type
346+
if not isinstance(type, PartialType):
347+
return type
348+
return None

mypy/checker.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@
4848
from mypy.visitor import StatementVisitor
4949
from mypy.join import join_types
5050
from mypy.treetransform import TransformVisitor
51+
from mypy.binder import ConditionalTypeBinder, get_declaration
5152
from mypy.meet import is_overlapping_types
52-
from mypy.binder import ConditionalTypeBinder
5353
from mypy.options import Options
5454

5555
from mypy import experiments
@@ -1221,10 +1221,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
12211221
" to a variable of type '{}'".format(lvalue_type), rvalue)
12221222
return
12231223
if rvalue_type and infer_lvalue_type:
1224-
self.binder.assign_type(lvalue,
1225-
rvalue_type,
1226-
lvalue_type,
1227-
False)
1224+
self.binder.assign_type(lvalue, rvalue_type, lvalue_type, False)
12281225
elif index_lvalue:
12291226
self.check_indexed_assignment(index_lvalue, rvalue, lvalue)
12301227

@@ -1927,7 +1924,6 @@ def visit_assert_stmt(self, s: AssertStmt) -> None:
19271924

19281925
# If this is asserting some isinstance check, bind that type in the following code
19291926
true_map, _ = self.find_isinstance_check(s.expr)
1930-
19311927
self.push_type_map(true_map)
19321928

19331929
def visit_raise_stmt(self, s: RaiseStmt) -> None:
@@ -2171,10 +2167,8 @@ def visit_del_stmt(self, s: DelStmt) -> None:
21712167
s.expr.accept(self.expr_checker)
21722168
for elt in flatten(s.expr):
21732169
if isinstance(elt, NameExpr):
2174-
self.binder.assign_type(elt,
2175-
DeletedType(source=elt.name),
2176-
self.binder.get_declaration(elt),
2177-
False)
2170+
self.binder.assign_type(elt, DeletedType(source=elt.name),
2171+
get_declaration(elt), False)
21782172

21792173
def visit_decorator(self, e: Decorator) -> None:
21802174
for d in e.decorators:
@@ -2463,7 +2457,7 @@ def push_type_map(self, type_map: Optional[Dict[Expression, Type]]) -> None:
24632457
self.binder.unreachable()
24642458
else:
24652459
for expr, type in type_map.items():
2466-
self.binder.push(expr, type)
2460+
self.binder.put(expr, type)
24672461

24682462
# Data structure returned by find_isinstance_check representing
24692463
# information learned from the truth or falsehood of a condition. The

mypy/checkexpr.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,13 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
160160
return result
161161

162162
def analyze_var_ref(self, var: Var, context: Context) -> Type:
163-
if not var.type:
163+
if var.type:
164+
return var.type
165+
else:
164166
if not var.is_ready and self.chk.in_checked_function():
165167
self.chk.handle_cannot_determine_type(var.name(), context)
166168
# Implicit 'Any' type.
167169
return AnyType()
168-
else:
169-
# Look up local type of variable with type (inferred or explicit).
170-
val = self.chk.binder.get(var)
171-
if val is None:
172-
return var.type
173-
else:
174-
return val
175170

176171
def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type:
177172
"""Type check a call expression."""
@@ -1954,7 +1949,7 @@ def check_for_comp(self, e: Union[GeneratorExpr, DictionaryComprehension]) -> No
19541949

19551950
if true_map:
19561951
for var, type in true_map.items():
1957-
self.chk.binder.push(var, type)
1952+
self.chk.binder.put(var, type)
19581953

19591954
def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
19601955
cond_type = self.accept(e.cond)

mypy/nodes.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,6 @@ class Node(Context):
116116
line = -1
117117
column = -1
118118

119-
# TODO: Move to Expression
120-
# See [Note Literals and literal_hash] below
121-
literal = LITERAL_NO
122-
literal_hash = None # type: Key
123-
124119
def __str__(self) -> str:
125120
ans = self.accept(mypy.strconv.StrConv())
126121
if ans is None:
@@ -161,6 +156,9 @@ def accept(self, visitor: StatementVisitor[T]) -> T:
161156

162157
class Expression(Node):
163158
"""An expression node."""
159+
literal = LITERAL_NO
160+
literal_hash = None # type: Key
161+
164162
def accept(self, visitor: ExpressionVisitor[T]) -> T:
165163
raise RuntimeError('Not implemented')
166164

0 commit comments

Comments
 (0)