Skip to content

Commit 45bed9c

Browse files
authored
Optimization: Remove expensive context manager in type analyzer (#14357)
This makes mypy a bit faster and the implementation seems a little cleaner as well. (Various small optimizations, including this, together netted a 6% performance improvement in self check.)
1 parent 20e9733 commit 45bed9c

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

mypy/typeanal.py

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,13 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
268268
self.api.record_incomplete_ref()
269269
# Always allow ParamSpec for placeholders, if they are actually not valid,
270270
# they will be reported later, after we resolve placeholders.
271-
with self.set_allow_param_spec_literals(True):
272-
return PlaceholderType(
273-
node.fullname, self.anal_array(t.args, allow_param_spec=True), t.line
274-
)
271+
return PlaceholderType(
272+
node.fullname,
273+
self.anal_array(
274+
t.args, allow_param_spec=True, allow_param_spec_literals=True
275+
),
276+
t.line,
277+
)
275278
else:
276279
if self.api.final_iteration:
277280
self.cannot_resolve_type(t)
@@ -382,10 +385,13 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
382385
return special
383386
if isinstance(node, TypeAlias):
384387
self.aliases_used.add(fullname)
385-
with self.set_allow_param_spec_literals(node.has_param_spec_type):
386-
an_args = self.anal_array(t.args, allow_param_spec=True)
387-
if node.has_param_spec_type and len(node.alias_tvars) == 1:
388-
an_args = self.pack_paramspec_args(an_args)
388+
an_args = self.anal_array(
389+
t.args,
390+
allow_param_spec=True,
391+
allow_param_spec_literals=node.has_param_spec_type,
392+
)
393+
if node.has_param_spec_type and len(node.alias_tvars) == 1:
394+
an_args = self.pack_paramspec_args(an_args)
389395

390396
disallow_any = self.options.disallow_any_generics and not self.is_typeshed_stub
391397
res = expand_type_alias(
@@ -660,17 +666,22 @@ def analyze_type_with_type_info(
660666
fallback = Instance(info, [AnyType(TypeOfAny.special_form)], ctx.line)
661667
return TupleType(self.anal_array(args), fallback, ctx.line)
662668

663-
# This is a heuristic: it will be checked later anyways but the error
664-
# message may be worse.
665-
with self.set_allow_param_spec_literals(info.has_param_spec_type):
666-
# Analyze arguments and (usually) construct Instance type. The
667-
# number of type arguments and their values are
668-
# checked only later, since we do not always know the
669-
# valid count at this point. Thus we may construct an
670-
# Instance with an invalid number of type arguments.
671-
instance = Instance(
672-
info, self.anal_array(args, allow_param_spec=True), ctx.line, ctx.column
673-
)
669+
# Analyze arguments and (usually) construct Instance type. The
670+
# number of type arguments and their values are
671+
# checked only later, since we do not always know the
672+
# valid count at this point. Thus we may construct an
673+
# Instance with an invalid number of type arguments.
674+
#
675+
# We allow ParamSpec literals based on a heuristic: it will be
676+
# checked later anyways but the error message may be worse.
677+
instance = Instance(
678+
info,
679+
self.anal_array(
680+
args, allow_param_spec=True, allow_param_spec_literals=info.has_param_spec_type
681+
),
682+
ctx.line,
683+
ctx.column,
684+
)
674685
if len(info.type_vars) == 1 and info.has_param_spec_type:
675686
instance.args = tuple(self.pack_paramspec_args(instance.args))
676687

@@ -1466,11 +1477,19 @@ def is_defined_type_var(self, tvar: str, context: Context) -> bool:
14661477
return self.tvar_scope.get_binding(tvar_node) is not None
14671478

14681479
def anal_array(
1469-
self, a: Iterable[Type], nested: bool = True, *, allow_param_spec: bool = False
1480+
self,
1481+
a: Iterable[Type],
1482+
nested: bool = True,
1483+
*,
1484+
allow_param_spec: bool = False,
1485+
allow_param_spec_literals: bool = False,
14701486
) -> list[Type]:
1487+
old_allow_param_spec_literals = self.allow_param_spec_literals
1488+
self.allow_param_spec_literals = allow_param_spec_literals
14711489
res: list[Type] = []
14721490
for t in a:
14731491
res.append(self.anal_type(t, nested, allow_param_spec=allow_param_spec))
1492+
self.allow_param_spec_literals = old_allow_param_spec_literals
14741493
return self.check_unpacks_in_list(res)
14751494

14761495
def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = False) -> Type:
@@ -1558,15 +1577,6 @@ def tuple_type(self, items: list[Type]) -> TupleType:
15581577
any_type = AnyType(TypeOfAny.special_form)
15591578
return TupleType(items, fallback=self.named_type("builtins.tuple", [any_type]))
15601579

1561-
@contextmanager
1562-
def set_allow_param_spec_literals(self, to: bool) -> Iterator[None]:
1563-
old = self.allow_param_spec_literals
1564-
try:
1565-
self.allow_param_spec_literals = to
1566-
yield
1567-
finally:
1568-
self.allow_param_spec_literals = old
1569-
15701580

15711581
TypeVarLikeList = List[Tuple[str, TypeVarLikeExpr]]
15721582

0 commit comments

Comments
 (0)