Skip to content

Commit c414464

Browse files
authored
Optimize implementation of TypedDict types for **kwds (#14316)
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.
1 parent fcd705d commit c414464

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

mypy/types.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1757,7 +1757,7 @@ def copy_modified(
17571757
from_concatenate: Bogus[bool] = _dummy,
17581758
unpack_kwargs: Bogus[bool] = _dummy,
17591759
) -> CT:
1760-
return type(self)(
1760+
modified = CallableType(
17611761
arg_types=arg_types if arg_types is not _dummy else self.arg_types,
17621762
arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds,
17631763
arg_names=arg_names if arg_names is not _dummy else self.arg_names,
@@ -1782,6 +1782,9 @@ def copy_modified(
17821782
),
17831783
unpack_kwargs=unpack_kwargs if unpack_kwargs is not _dummy else self.unpack_kwargs,
17841784
)
1785+
# Optimization: Only NewTypes are supported as subtypes since
1786+
# the class is effectively final, so we can use a cast safely.
1787+
return cast(CT, modified)
17851788

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

19771980
def with_unpacked_kwargs(self) -> NormalizedCallableType:
19781981
if not self.unpack_kwargs:
1979-
return NormalizedCallableType(self.copy_modified())
1982+
return cast(NormalizedCallableType, self)
19801983
last_type = get_proper_type(self.arg_types[-1])
19811984
assert isinstance(last_type, TypedDictType)
19821985
extra_kinds = [
@@ -2126,7 +2129,9 @@ def get_name(self) -> str | None:
21262129
return self._items[0].name
21272130

21282131
def with_unpacked_kwargs(self) -> Overloaded:
2129-
return Overloaded([i.with_unpacked_kwargs() for i in self.items])
2132+
if any(i.unpack_kwargs for i in self.items):
2133+
return Overloaded([i.with_unpacked_kwargs() for i in self.items])
2134+
return self
21302135

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

0 commit comments

Comments
 (0)