Skip to content

Commit e8ae122

Browse files
authored
Couple obvious optimizations for type aliases (#8099)
This PR: * Removes three unused slots * Makes recursivity test once per alias * Documents an existing optimization (accidentally made before) The effect of this it at the limit of precision on my laptop, but it looks like this gives around 1% speed-up (for cold runs).
1 parent 9d10a3e commit e8ae122

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

mypy/nodes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2741,7 +2741,7 @@ def f(x: B[T]) -> T: ... # without T, Any would be used here
27412741
line and column: Line an column on the original alias definition.
27422742
"""
27432743
__slots__ = ('target', '_fullname', 'alias_tvars', 'no_args', 'normalized',
2744-
'line', 'column', 'assuming', 'assuming_proper', 'inferring')
2744+
'line', 'column', '_is_recursive')
27452745

27462746
def __init__(self, target: 'mypy.types.Type', fullname: str, line: int, column: int,
27472747
*,
@@ -2755,6 +2755,9 @@ def __init__(self, target: 'mypy.types.Type', fullname: str, line: int, column:
27552755
self.alias_tvars = alias_tvars
27562756
self.no_args = no_args
27572757
self.normalized = normalized
2758+
# This attribute is manipulated by TypeAliasType. If non-None,
2759+
# it is the cached value.
2760+
self._is_recursive = None # type: Optional[bool]
27582761
super().__init__(line, column)
27592762

27602763
@property

mypy/semanal.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,6 +2514,9 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> bool:
25142514
# so we need to replace it with non-explicit Anys.
25152515
if not has_placeholder(res):
25162516
res = make_any_non_explicit(res)
2517+
# Note: with the new (lazy) type alias representation we only need to set no_args to True
2518+
# if the expected number of arguments is non-zero, so that aliases like A = List work.
2519+
# However, eagerly expanding aliases like Text = str is a nice performance optimization.
25172520
no_args = isinstance(res, Instance) and not res.args # type: ignore
25182521
fix_instance_types(res, self.fail, self.note)
25192522
alias_node = TypeAlias(res, self.qualified_name(lvalue.name), s.line, s.column,

mypy/types.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,13 @@ class Node:
166166
can be represented in a tree-like manner.
167167
"""
168168

169-
__slots__ = ('alias', 'args', 'line', 'column', 'type_ref', '_is_recursive')
169+
__slots__ = ('alias', 'args', 'line', 'column', 'type_ref')
170170

171171
def __init__(self, alias: Optional[mypy.nodes.TypeAlias], args: List[Type],
172172
line: int = -1, column: int = -1) -> None:
173173
self.alias = alias
174174
self.args = args
175175
self.type_ref = None # type: Optional[str]
176-
self._is_recursive = None # type: Optional[bool]
177176
super().__init__(line, column)
178177

179178
def _expand_once(self) -> Type:
@@ -212,10 +211,13 @@ def expand_all_if_possible(self) -> Optional['ProperType']:
212211

213212
@property
214213
def is_recursive(self) -> bool:
215-
if self._is_recursive is not None:
216-
return self._is_recursive
217-
is_recursive = self.expand_all_if_possible() is None
218-
self._is_recursive = is_recursive
214+
assert self.alias is not None, 'Unfixed type alias'
215+
is_recursive = self.alias._is_recursive
216+
if is_recursive is None:
217+
is_recursive = self.expand_all_if_possible() is None
218+
# We cache the value on the underlying TypeAlias node as an optimization,
219+
# since the value is the same for all instances of the same alias.
220+
self.alias._is_recursive = is_recursive
219221
return is_recursive
220222

221223
def can_be_true_default(self) -> bool:

0 commit comments

Comments
 (0)