Skip to content

Commit 87f4dc8

Browse files
authored
Mypy micro-optimizations (batch 1/3) (#19768)
Several mypy micro-optimizations. Together with batches 2 and 3 these improve self check performance by 1.8%.
1 parent bf70dab commit 87f4dc8

File tree

9 files changed

+29
-22
lines changed

9 files changed

+29
-22
lines changed

mypy/applytype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ def visit_callable_type(self, t: CallableType) -> Type:
243243
self.bound_tvars -= set(found_vars)
244244

245245
assert isinstance(result, ProperType) and isinstance(result, CallableType)
246-
result.variables = list(result.variables) + found_vars
246+
result.variables = result.variables + tuple(found_vars)
247247
return result
248248

249249
def visit_type_var(self, t: TypeVarType) -> Type:

mypy/binder.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,12 @@ def update_from_options(self, frames: list[Frame]) -> bool:
250250
options are the same.
251251
"""
252252
all_reachable = all(not f.unreachable for f in frames)
253-
frames = [f for f in frames if not f.unreachable]
253+
if not all_reachable:
254+
frames = [f for f in frames if not f.unreachable]
254255
changed = False
255-
keys = {key for f in frames for key in f.types}
256-
256+
keys = [key for f in frames for key in f.types]
257+
if len(keys) > 1:
258+
keys = list(set(keys))
257259
for key in keys:
258260
current_value = self._get(key)
259261
resulting_values = [f.types.get(key, current_value) for f in frames]

mypy/plugins/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ def _add_method_by_spec(
360360

361361
signature = CallableType(arg_types, arg_kinds, arg_names, return_type, function_type)
362362
if tvar_defs:
363-
signature.variables = tvar_defs
363+
signature.variables = tuple(tvar_defs)
364364

365365
func = FuncDef(name, args, Block([PassStmt()]))
366366
func.info = info

mypy/semanal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ def analyze_func_def(self, defn: FuncDef) -> None:
995995
if has_self_type and self.type is not None:
996996
info = self.type
997997
if info.self_type is not None:
998-
result.variables = [info.self_type] + list(result.variables)
998+
result.variables = (info.self_type,) + result.variables
999999
defn.type = result
10001000
self.add_type_alias_deps(analyzer.aliases_used)
10011001
self.check_function_signature(defn)

mypy/semanal_namedtuple.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ def add_method(
606606
arg_kinds = [arg.kind for arg in args]
607607
assert None not in types
608608
signature = CallableType(cast(list[Type], types), arg_kinds, items, ret, function_type)
609-
signature.variables = [self_type]
609+
signature.variables = (self_type,)
610610
func = FuncDef(funcname, args, Block([]))
611611
func.info = info
612612
func.is_class = is_classmethod

mypy/server/aststrip.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def visit_func_def(self, node: FuncDef) -> None:
165165
# in order to get the state exactly as it was before semantic analysis.
166166
# See also #4814.
167167
assert isinstance(node.type, CallableType)
168-
node.type.variables = []
168+
node.type.variables = ()
169169
with self.enter_method(node.info) if node.info else nullcontext():
170170
super().visit_func_def(node)
171171

mypy/type_visitor.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def visit_instance(self, t: Instance, /) -> Type:
228228
last_known_value = raw_last_known_value
229229
return Instance(
230230
typ=t.type,
231-
args=self.translate_types(t.args),
231+
args=self.translate_type_tuple(t.args),
232232
line=t.line,
233233
column=t.column,
234234
last_known_value=last_known_value,
@@ -242,7 +242,7 @@ def visit_param_spec(self, t: ParamSpecType, /) -> Type:
242242
return t
243243

244244
def visit_parameters(self, t: Parameters, /) -> Type:
245-
return t.copy_modified(arg_types=self.translate_types(t.arg_types))
245+
return t.copy_modified(arg_types=self.translate_type_list(t.arg_types))
246246

247247
def visit_type_var_tuple(self, t: TypeVarTupleType, /) -> Type:
248248
return t
@@ -255,14 +255,14 @@ def visit_unpack_type(self, t: UnpackType, /) -> Type:
255255

256256
def visit_callable_type(self, t: CallableType, /) -> Type:
257257
return t.copy_modified(
258-
arg_types=self.translate_types(t.arg_types),
258+
arg_types=self.translate_type_list(t.arg_types),
259259
ret_type=t.ret_type.accept(self),
260260
variables=self.translate_variables(t.variables),
261261
)
262262

263263
def visit_tuple_type(self, t: TupleType, /) -> Type:
264264
return TupleType(
265-
self.translate_types(t.items),
265+
self.translate_type_list(t.items),
266266
# TODO: This appears to be unsafe.
267267
cast(Any, t.partial_fallback.accept(self)),
268268
t.line,
@@ -299,7 +299,7 @@ def visit_union_type(self, t: UnionType, /) -> Type:
299299
return cached
300300

301301
result = UnionType(
302-
self.translate_types(t.items),
302+
self.translate_type_list(t.items),
303303
t.line,
304304
t.column,
305305
uses_pep604_syntax=t.uses_pep604_syntax,
@@ -308,9 +308,12 @@ def visit_union_type(self, t: UnionType, /) -> Type:
308308
self.set_cached(t, result)
309309
return result
310310

311-
def translate_types(self, types: Iterable[Type]) -> list[Type]:
311+
def translate_type_list(self, types: list[Type]) -> list[Type]:
312312
return [t.accept(self) for t in types]
313313

314+
def translate_type_tuple(self, types: tuple[Type, ...]) -> tuple[Type, ...]:
315+
return tuple(t.accept(self) for t in types)
316+
314317
def translate_variables(
315318
self, variables: Sequence[TypeVarLikeType]
316319
) -> Sequence[TypeVarLikeType]:

mypy/typeanal.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,7 @@ def infer_type_variables(
18201820

18211821
def bind_function_type_variables(
18221822
self, fun_type: CallableType, defn: Context
1823-
) -> tuple[Sequence[TypeVarLikeType], bool]:
1823+
) -> tuple[tuple[TypeVarLikeType, ...], bool]:
18241824
"""Find the type variables of the function type and bind them in our tvar_scope"""
18251825
has_self_type = False
18261826
if fun_type.variables:
@@ -1835,7 +1835,7 @@ def bind_function_type_variables(
18351835
assert isinstance(var_expr, TypeVarLikeExpr)
18361836
binding = self.tvar_scope.bind_new(var.name, var_expr)
18371837
defs.append(binding)
1838-
return defs, has_self_type
1838+
return tuple(defs), has_self_type
18391839
typevars, has_self_type = self.infer_type_variables(fun_type)
18401840
# Do not define a new type variable if already defined in scope.
18411841
typevars = [
@@ -1849,7 +1849,7 @@ def bind_function_type_variables(
18491849
binding = self.tvar_scope.bind_new(name, tvar)
18501850
defs.append(binding)
18511851

1852-
return defs, has_self_type
1852+
return tuple(defs), has_self_type
18531853

18541854
def is_defined_type_var(self, tvar: str, context: Context) -> bool:
18551855
tvar_node = self.lookup_qualified(tvar, context)

mypy/types.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,14 +2104,12 @@ def __init__(
21042104
) -> None:
21052105
super().__init__(line, column)
21062106
assert len(arg_types) == len(arg_kinds) == len(arg_names)
2107-
for t, k in zip(arg_types, arg_kinds):
2107+
self.arg_types = list(arg_types)
2108+
for t in self.arg_types:
21082109
if isinstance(t, ParamSpecType):
21092110
assert not t.prefix.arg_types
21102111
# TODO: should we assert that only ARG_STAR contain ParamSpecType?
21112112
# See testParamSpecJoin, that relies on passing e.g `P.args` as plain argument.
2112-
if variables is None:
2113-
variables = []
2114-
self.arg_types = list(arg_types)
21152113
self.arg_kinds = arg_kinds
21162114
self.arg_names = list(arg_names)
21172115
self.min_args = arg_kinds.count(ARG_POS)
@@ -2123,7 +2121,11 @@ def __init__(
21232121
# * If it is a non-decorated function, FuncDef is the definition
21242122
# * If it is a decorated function, enclosing Decorator is the definition
21252123
self.definition = definition
2126-
self.variables = variables
2124+
self.variables: tuple[TypeVarLikeType, ...]
2125+
if variables is None:
2126+
self.variables = ()
2127+
else:
2128+
self.variables = tuple(variables)
21272129
self.is_ellipsis_args = is_ellipsis_args
21282130
self.implicit = implicit
21292131
self.special_sig = special_sig

0 commit comments

Comments
 (0)