Skip to content

Commit a009879

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

File tree

5 files changed

+26
-25
lines changed

5 files changed

+26
-25
lines changed

mypy/argmap.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def __init__(self, context: ArgumentInferContext) -> None:
167167
# Next tuple *args index to use.
168168
self.tuple_index = 0
169169
# Keyword arguments in TypedDict **kwargs used.
170-
self.kwargs_used: set[str] = set()
170+
self.kwargs_used: set[str] | None = None
171171
# Type context for `*` and `**` arg kinds.
172172
self.context = context
173173

@@ -241,6 +241,8 @@ def expand_actual_type(
241241
from mypy.subtypes import is_subtype
242242

243243
if isinstance(actual_type, TypedDictType):
244+
if self.kwargs_used is None:
245+
self.kwargs_used = set()
244246
if formal_kind != nodes.ARG_STAR2 and formal_name in actual_type.items:
245247
# Lookup type based on keyword argument name.
246248
assert formal_name is not None

mypy/checkexpr.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,11 @@ def allow_fast_container_literal(t: Type) -> bool:
248248
)
249249

250250

251-
def extract_refexpr_names(expr: RefExpr) -> set[str]:
251+
def extract_refexpr_names(expr: RefExpr, output: set[str]) -> None:
252252
"""Recursively extracts all module references from a reference expression.
253253
254254
Note that currently, the only two subclasses of RefExpr are NameExpr and
255255
MemberExpr."""
256-
output: set[str] = set()
257256
while isinstance(expr.node, MypyFile) or expr.fullname:
258257
if isinstance(expr.node, MypyFile) and expr.fullname:
259258
# If it's None, something's wrong (perhaps due to an
@@ -277,7 +276,6 @@ def extract_refexpr_names(expr: RefExpr) -> set[str]:
277276
break
278277
else:
279278
raise AssertionError(f"Unknown RefExpr subclass: {type(expr)}")
280-
return output
281279

282280

283281
class Finished(Exception):
@@ -372,7 +370,7 @@ def visit_name_expr(self, e: NameExpr) -> Type:
372370
373371
It can be of any kind: local, member or global.
374372
"""
375-
self.chk.module_refs.update(extract_refexpr_names(e))
373+
extract_refexpr_names(e, self.chk.module_refs)
376374
result = self.analyze_ref_expr(e)
377375
narrowed = self.narrow_type_from_binder(e, result)
378376
self.chk.check_deprecated(e.node, e)
@@ -3345,7 +3343,7 @@ def check_union_call(
33453343

33463344
def visit_member_expr(self, e: MemberExpr, is_lvalue: bool = False) -> Type:
33473345
"""Visit member expression (of form e.id)."""
3348-
self.chk.module_refs.update(extract_refexpr_names(e))
3346+
extract_refexpr_names(e, self.chk.module_refs)
33493347
result = self.analyze_ordinary_member_access(e, is_lvalue)
33503348
narrowed = self.narrow_type_from_binder(e, result)
33513349
self.chk.warn_deprecated(e.node, e)

mypy/expandtype.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class ExpandTypeVisitor(TrivialSyntheticTypeTranslator):
182182
def __init__(self, variables: Mapping[TypeVarId, Type]) -> None:
183183
super().__init__()
184184
self.variables = variables
185-
self.recursive_tvar_guard: dict[TypeVarId, Type | None] = {}
185+
self.recursive_tvar_guard: dict[TypeVarId, Type | None] | None = None
186186

187187
def visit_unbound_type(self, t: UnboundType) -> Type:
188188
return t
@@ -246,6 +246,8 @@ def visit_type_var(self, t: TypeVarType) -> Type:
246246
# If I try to remove this special-casing ~40 tests fail on reveal_type().
247247
return repl.copy_modified(last_known_value=None)
248248
if isinstance(repl, TypeVarType) and repl.has_default():
249+
if self.recursive_tvar_guard is None:
250+
self.recursive_tvar_guard = {}
249251
if (tvar_id := repl.id) in self.recursive_tvar_guard:
250252
return self.recursive_tvar_guard[tvar_id] or repl
251253
self.recursive_tvar_guard[tvar_id] = None

mypy/messages.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -649,26 +649,11 @@ def incompatible_argument(
649649
else:
650650
base = extract_type(name)
651651

652-
for method, op in op_methods_to_symbols.items():
653-
for variant in method, "__r" + method[2:]:
654-
# FIX: do not rely on textual formatting
655-
if name.startswith(f'"{variant}" of'):
656-
if op == "in" or variant != method:
657-
# Reversed order of base/argument.
658-
return self.unsupported_operand_types(
659-
op, arg_type, base, context, code=codes.OPERATOR
660-
)
661-
else:
662-
return self.unsupported_operand_types(
663-
op, base, arg_type, context, code=codes.OPERATOR
664-
)
665-
666652
if name.startswith('"__getitem__" of'):
667653
return self.invalid_index_type(
668654
arg_type, callee.arg_types[n - 1], base, context, code=codes.INDEX
669655
)
670-
671-
if name.startswith('"__setitem__" of'):
656+
elif name.startswith('"__setitem__" of'):
672657
if n == 1:
673658
return self.invalid_index_type(
674659
arg_type, callee.arg_types[n - 1], base, context, code=codes.INDEX
@@ -684,6 +669,20 @@ def incompatible_argument(
684669
message_registry.INCOMPATIBLE_TYPES_IN_ASSIGNMENT.with_additional_msg(info)
685670
)
686671
return self.fail(error_msg.value, context, code=error_msg.code)
672+
elif name.startswith('"__'):
673+
for method, op in op_methods_to_symbols.items():
674+
for variant in method, "__r" + method[2:]:
675+
# FIX: do not rely on textual formatting
676+
if name.startswith(f'"{variant}" of'):
677+
if op == "in" or variant != method:
678+
# Reversed order of base/argument.
679+
return self.unsupported_operand_types(
680+
op, arg_type, base, context, code=codes.OPERATOR
681+
)
682+
else:
683+
return self.unsupported_operand_types(
684+
op, base, arg_type, context, code=codes.OPERATOR
685+
)
687686

688687
target = f"to {name} "
689688

mypy/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ class TypeVarId:
543543
# function type variables.
544544

545545
# Metavariables are allocated unique ids starting from 1.
546-
raw_id: int
546+
raw_id: Final[int]
547547

548548
# Level of the variable in type inference. Currently either 0 for
549549
# declared types, or 1 for type inference metavariables.
@@ -586,7 +586,7 @@ def __ne__(self, other: object) -> bool:
586586
return not (self == other)
587587

588588
def __hash__(self) -> int:
589-
return hash((self.raw_id, self.meta_level, self.namespace))
589+
return self.raw_id ^ (self.meta_level << 8) ^ hash(self.namespace)
590590

591591
def is_meta_var(self) -> bool:
592592
return self.meta_level > 0

0 commit comments

Comments
 (0)