Skip to content

Commit e170f6b

Browse files
msullivanJukkaL
authored andcommitted
Make Frame stop being a dict subclass (python#5761)
This allows the 'unreachable' flag to not need to be accessed via GetAttr, and for dict operations to be done via dict primitives. Amazingly, this gives a ~200ms speedup on self check (like 6%!).
1 parent 15d2668 commit e170f6b

File tree

1 file changed

+13
-19
lines changed

1 file changed

+13
-19
lines changed

mypy/binder.py

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
BindableExpression = Union[IndexExpr, MemberExpr, NameExpr]
1919

2020

21-
class Frame(Dict[Key, Type]):
21+
class Frame:
2222
"""A Frame represents a specific point in the execution of a program.
2323
It carries information about the current types of expressions at
2424
that point, arising either from assignments to those expressions
@@ -31,13 +31,7 @@ class Frame(Dict[Key, Type]):
3131
"""
3232

3333
def __init__(self) -> None:
34-
self.unreachable = False
35-
36-
37-
class DeclarationsFrame(Dict[Key, Optional[Type]]):
38-
"""Same as above, but allowed to have None values."""
39-
40-
def __init__(self) -> None:
34+
self.types = {} # type: Dict[Key, Type]
4135
self.unreachable = False
4236

4337

@@ -89,7 +83,7 @@ def __init__(self) -> None:
8983

9084
# Maps literal_hash(expr) to get_declaration(expr)
9185
# for every expr stored in the binder
92-
self.declarations = DeclarationsFrame()
86+
self.declarations = {} # type: Dict[Key, Optional[Type]]
9387
# Set of other keys to invalidate if a key is changed, e.g. x -> {x.a, x[0]}
9488
# Whenever a new key (e.g. x.a.b) is added, we update this
9589
self.dependencies = {} # type: Dict[Key, Set[Key]]
@@ -117,14 +111,14 @@ def push_frame(self) -> Frame:
117111
return f
118112

119113
def _put(self, key: Key, type: Type, index: int=-1) -> None:
120-
self.frames[index][key] = type
114+
self.frames[index].types[key] = type
121115

122116
def _get(self, key: Key, index: int=-1) -> Optional[Type]:
123117
if index < 0:
124118
index += len(self.frames)
125119
for i in range(index, -1, -1):
126-
if key in self.frames[i]:
127-
return self.frames[i][key]
120+
if key in self.frames[i].types:
121+
return self.frames[i].types[key]
128122
return None
129123

130124
def put(self, expr: Expression, typ: Type) -> None:
@@ -161,8 +155,8 @@ def cleanse(self, expr: Expression) -> None:
161155
def _cleanse_key(self, key: Key) -> None:
162156
"""Remove all references to a key from the binder."""
163157
for frame in self.frames:
164-
if key in frame:
165-
del frame[key]
158+
if key in frame.types:
159+
del frame.types[key]
166160

167161
def update_from_options(self, frames: List[Frame]) -> bool:
168162
"""Update the frame to reflect that each key will be updated
@@ -174,11 +168,11 @@ def update_from_options(self, frames: List[Frame]) -> bool:
174168

175169
frames = [f for f in frames if not f.unreachable]
176170
changed = False
177-
keys = set(key for f in frames for key in f)
171+
keys = set(key for f in frames for key in f.types)
178172

179173
for key in keys:
180174
current_value = self._get(key)
181-
resulting_values = [f.get(key, current_value) for f in frames]
175+
resulting_values = [f.types.get(key, current_value) for f in frames]
182176
if any(x is None for x in resulting_values):
183177
# We didn't know anything about key before
184178
# (current_value must be None), and we still don't
@@ -321,8 +315,8 @@ def most_recent_enclosing_type(self, expr: BindableExpression, type: Type) -> Op
321315
key = literal_hash(expr)
322316
assert key is not None
323317
enclosers = ([get_declaration(expr)] +
324-
[f[key] for f in self.frames
325-
if key in f and is_subtype(type, f[key])])
318+
[f.types[key] for f in self.frames
319+
if key in f.types and is_subtype(type, f.types[key])])
326320
return enclosers[-1]
327321

328322
def allow_jump(self, index: int) -> None:
@@ -332,7 +326,7 @@ def allow_jump(self, index: int) -> None:
332326
index += len(self.options_on_return)
333327
frame = Frame()
334328
for f in self.frames[index + 1:]:
335-
frame.update(f)
329+
frame.types.update(f.types)
336330
if f.unreachable:
337331
frame.unreachable = True
338332
self.options_on_return[index].append(frame)

0 commit comments

Comments
 (0)