Skip to content

Commit

Permalink
Optimize implementation of TypedDict types for **kwds (#14316)
Browse files Browse the repository at this point in the history
The implementation copied lots of callable types even when not using
the new feature, which was expensive. Now we only generate a copy if a
callable actually uses TypedDict types for **kwds.

This made self check 7-8% faster (when compiled with -O0).

The original implementation was in
#13471.
  • Loading branch information
JukkaL committed Dec 20, 2022
1 parent fcd705d commit c414464
Showing 1 changed file with 8 additions and 3 deletions.
11 changes: 8 additions & 3 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1757,7 +1757,7 @@ def copy_modified(
from_concatenate: Bogus[bool] = _dummy,
unpack_kwargs: Bogus[bool] = _dummy,
) -> CT:
return type(self)(
modified = CallableType(
arg_types=arg_types if arg_types is not _dummy else self.arg_types,
arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds,
arg_names=arg_names if arg_names is not _dummy else self.arg_names,
Expand All @@ -1782,6 +1782,9 @@ def copy_modified(
),
unpack_kwargs=unpack_kwargs if unpack_kwargs is not _dummy else self.unpack_kwargs,
)
# Optimization: Only NewTypes are supported as subtypes since
# the class is effectively final, so we can use a cast safely.
return cast(CT, modified)

def var_arg(self) -> FormalArgument | None:
"""The formal argument for *args."""
Expand Down Expand Up @@ -1976,7 +1979,7 @@ def expand_param_spec(

def with_unpacked_kwargs(self) -> NormalizedCallableType:
if not self.unpack_kwargs:
return NormalizedCallableType(self.copy_modified())
return cast(NormalizedCallableType, self)
last_type = get_proper_type(self.arg_types[-1])
assert isinstance(last_type, TypedDictType)
extra_kinds = [
Expand Down Expand Up @@ -2126,7 +2129,9 @@ def get_name(self) -> str | None:
return self._items[0].name

def with_unpacked_kwargs(self) -> Overloaded:
return Overloaded([i.with_unpacked_kwargs() for i in self.items])
if any(i.unpack_kwargs for i in self.items):
return Overloaded([i.with_unpacked_kwargs() for i in self.items])
return self

def accept(self, visitor: TypeVisitor[T]) -> T:
return visitor.visit_overloaded(self)
Expand Down

0 comments on commit c414464

Please sign in to comment.