Skip to content

Commit 5f5871d

Browse files
authored
Micro-optimize ExpandTypeVisitor (#19461)
Specialize a hot for loop for the concrete `tuple` and `list` types. Also add a fast path for empty type arguments. The approach is similar to what I used in #19459. This is a part of a set of micro-optimizations that improve self check performance by ~5.5%.
1 parent ca738e5 commit 5f5871d

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

mypy/expandtype.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from collections.abc import Iterable, Mapping, Sequence
3+
from collections.abc import Iterable, Mapping
44
from typing import Final, TypeVar, cast, overload
55

66
from mypy.nodes import ARG_STAR, FakeInfo, Var
@@ -209,7 +209,11 @@ def visit_erased_type(self, t: ErasedType) -> Type:
209209
return t
210210

211211
def visit_instance(self, t: Instance) -> Type:
212-
args = self.expand_types_with_unpack(list(t.args))
212+
if len(t.args) == 0:
213+
# TODO: Why do we need to create a copy here?
214+
return t.copy_modified()
215+
216+
args = self.expand_type_tuple_with_unpack(t.args)
213217

214218
if isinstance(t.type, FakeInfo):
215219
# The type checker expands function definitions and bodies
@@ -431,7 +435,7 @@ def visit_overloaded(self, t: Overloaded) -> Type:
431435
items.append(new_item)
432436
return Overloaded(items)
433437

434-
def expand_types_with_unpack(self, typs: Sequence[Type]) -> list[Type]:
438+
def expand_type_list_with_unpack(self, typs: list[Type]) -> list[Type]:
435439
"""Expands a list of types that has an unpack."""
436440
items: list[Type] = []
437441
for item in typs:
@@ -441,8 +445,19 @@ def expand_types_with_unpack(self, typs: Sequence[Type]) -> list[Type]:
441445
items.append(item.accept(self))
442446
return items
443447

448+
def expand_type_tuple_with_unpack(self, typs: tuple[Type, ...]) -> list[Type]:
449+
"""Expands a tuple of types that has an unpack."""
450+
# Micro-optimization: Specialized variant of expand_type_list_with_unpack
451+
items: list[Type] = []
452+
for item in typs:
453+
if isinstance(item, UnpackType) and isinstance(item.type, TypeVarTupleType):
454+
items.extend(self.expand_unpack(item))
455+
else:
456+
items.append(item.accept(self))
457+
return items
458+
444459
def visit_tuple_type(self, t: TupleType) -> Type:
445-
items = self.expand_types_with_unpack(t.items)
460+
items = self.expand_type_list_with_unpack(t.items)
446461
if len(items) == 1:
447462
# Normalize Tuple[*Tuple[X, ...]] -> Tuple[X, ...]
448463
item = items[0]
@@ -510,7 +525,7 @@ def visit_type_type(self, t: TypeType) -> Type:
510525
def visit_type_alias_type(self, t: TypeAliasType) -> Type:
511526
# Target of the type alias cannot contain type variables (not bound by the type
512527
# alias itself), so we just expand the arguments.
513-
args = self.expand_types_with_unpack(t.args)
528+
args = self.expand_type_list_with_unpack(t.args)
514529
# TODO: normalize if target is Tuple, and args are [*tuple[X, ...]]?
515530
return t.copy_modified(args=args)
516531

0 commit comments

Comments
 (0)