Skip to content

Micro-optimize TypeTraverserVisitor #19459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions mypy/typetraverser.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def visit_param_spec(self, t: ParamSpecType, /) -> None:
t.default.accept(self)

def visit_parameters(self, t: Parameters, /) -> None:
self.traverse_types(t.arg_types)
self.traverse_type_list(t.arg_types)

def visit_type_var_tuple(self, t: TypeVarTupleType, /) -> None:
t.default.accept(self)
Expand All @@ -78,11 +78,11 @@ def visit_literal_type(self, t: LiteralType, /) -> None:
# Composite types

def visit_instance(self, t: Instance, /) -> None:
self.traverse_types(t.args)
self.traverse_type_tuple(t.args)

def visit_callable_type(self, t: CallableType, /) -> None:
# FIX generics
self.traverse_types(t.arg_types)
self.traverse_type_list(t.arg_types)
t.ret_type.accept(self)
t.fallback.accept(self)

Expand All @@ -93,15 +93,15 @@ def visit_callable_type(self, t: CallableType, /) -> None:
t.type_is.accept(self)

def visit_tuple_type(self, t: TupleType, /) -> None:
self.traverse_types(t.items)
self.traverse_type_list(t.items)
t.partial_fallback.accept(self)

def visit_typeddict_type(self, t: TypedDictType, /) -> None:
self.traverse_types(t.items.values())
t.fallback.accept(self)

def visit_union_type(self, t: UnionType, /) -> None:
self.traverse_types(t.items)
self.traverse_type_list(t.items)

def visit_overloaded(self, t: Overloaded, /) -> None:
self.traverse_types(t.items)
Expand All @@ -115,16 +115,16 @@ def visit_callable_argument(self, t: CallableArgument, /) -> None:
t.typ.accept(self)

def visit_unbound_type(self, t: UnboundType, /) -> None:
self.traverse_types(t.args)
self.traverse_type_tuple(t.args)

def visit_type_list(self, t: TypeList, /) -> None:
self.traverse_types(t.items)
self.traverse_type_list(t.items)

def visit_ellipsis_type(self, t: EllipsisType, /) -> None:
pass

def visit_placeholder_type(self, t: PlaceholderType, /) -> None:
self.traverse_types(t.args)
self.traverse_type_list(t.args)

def visit_partial_type(self, t: PartialType, /) -> None:
pass
Expand All @@ -136,7 +136,7 @@ def visit_type_alias_type(self, t: TypeAliasType, /) -> None:
# TODO: sometimes we want to traverse target as well
# We need to find a way to indicate explicitly the intent,
# maybe make this method abstract (like for TypeTranslator)?
self.traverse_types(t.args)
self.traverse_type_list(t.args)

def visit_unpack_type(self, t: UnpackType, /) -> None:
t.type.accept(self)
Expand All @@ -146,3 +146,13 @@ def visit_unpack_type(self, t: UnpackType, /) -> None:
def traverse_types(self, types: Iterable[Type], /) -> None:
for typ in types:
typ.accept(self)

def traverse_type_list(self, types: list[Type], /) -> None:
# Micro-optimization: Specialized for lists
for typ in types:
typ.accept(self)

def traverse_type_tuple(self, types: tuple[Type, ...], /) -> None:
# Micro-optimization: Specialized for tuples
for typ in types:
typ.accept(self)