Skip to content

Commit f5fef69

Browse files
committed
Put it together with other caches
1 parent fce7464 commit f5fef69

2 files changed

Lines changed: 28 additions & 13 deletions

File tree

‎mypy/typeops.py‎

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import itertools
1111
from collections.abc import Callable, Iterable, Sequence
12-
from typing import Any, Final, TypeVar, cast
12+
from typing import Any, TypeVar, cast
1313

1414
import mypy.subtypes
1515
from mypy.checker_state import checker_state
@@ -72,15 +72,10 @@
7272
instance_cache,
7373
remove_dups,
7474
)
75+
from mypy.typestate import BIND_SELF_CACHE_MAX_SIZE, type_state
7576
from mypy.typetraverser import TypeTraverserVisitor
7677
from mypy.typevars import fill_typevars
7778

78-
BindSelfCacheKey = tuple[CallableType, Type, bool, bool]
79-
BindSelfCacheValue = tuple[CallableType, Sequence[TypeVarLikeType]]
80-
81-
BIND_SELF_CACHE: Final[dict[BindSelfCacheKey, BindSelfCacheValue]] = {}
82-
BIND_SELF_CACHE_MAX_SIZE: Final = 10000
83-
8479

8580
def is_recursive_pair(s: Type, t: Type) -> bool:
8681
"""Is this a pair of recursive types?
@@ -562,8 +557,8 @@ def bind_self_inner(
562557
# Only use cache for something that in not freshened (e.g. protocol access),
563558
# otherwise it would be pointless as each fresh meta variable is unique.
564559
cache_key = (func, original_type, is_classmethod, ignore_instances)
565-
if cache_key is not None and cache_key in BIND_SELF_CACHE:
566-
return BIND_SELF_CACHE[cache_key]
560+
if cache_key is not None and cache_key in type_state.bind_self_cache:
561+
return type_state.bind_self_cache[cache_key]
567562

568563
# Solve for these type arguments using the actual class or instance type.
569564
typeargs = infer_type_arguments(
@@ -589,9 +584,9 @@ def bind_self_inner(
589584
func = expand_type(func, {tv.id: arg for tv, arg in zip(self_vars, to_apply)})
590585
variables = [v for v in func.variables if v not in self_vars]
591586
if cache_key is not None:
592-
if len(BIND_SELF_CACHE) > BIND_SELF_CACHE_MAX_SIZE:
593-
BIND_SELF_CACHE.clear()
594-
BIND_SELF_CACHE[cache_key] = func, variables
587+
if len(type_state.bind_self_cache) > BIND_SELF_CACHE_MAX_SIZE:
588+
type_state.bind_self_cache.clear()
589+
type_state.bind_self_cache[cache_key] = func, variables
595590
else:
596591
variables = func.variables
597592
return func, variables

‎mypy/typestate.py‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,29 @@
55

66
from __future__ import annotations
77

8+
from collections.abc import Sequence
89
from typing import Final, TypeAlias as _TypeAlias
910

1011
from mypy.nodes import VARIANCE_NOT_READY, TypeInfo
1112
from mypy.server.trigger import make_trigger
12-
from mypy.types import Instance, Type, TypeVarId, TypeVarType, get_proper_type
13+
from mypy.types import (
14+
CallableType,
15+
Instance,
16+
Type,
17+
TypeVarId,
18+
TypeVarLikeType,
19+
TypeVarType,
20+
get_proper_type,
21+
)
1322

1423
MAX_NEGATIVE_CACHE_TYPES: Final = 1000
1524
MAX_NEGATIVE_CACHE_ENTRIES: Final = 10000
1625

26+
BindSelfCacheKey = tuple[CallableType, Type, bool, bool]
27+
BindSelfCacheValue = tuple[CallableType, Sequence[TypeVarLikeType]]
28+
29+
BIND_SELF_CACHE_MAX_SIZE: Final = 10000
30+
1731
# Represents that the 'left' instance is a subtype of the 'right' instance
1832
SubtypeRelationship: _TypeAlias = tuple[Instance, Instance]
1933

@@ -47,6 +61,10 @@ class TypeState:
4761
# Same as above but for negative subtyping results.
4862
_negative_subtype_caches: Final[SubtypeCache]
4963

64+
# A dedicated lightweight cache for bind_self(), which may be slow because of type
65+
# inference in some scenarios involving protocols with non-trivial self-types.
66+
bind_self_cache: Final[dict[BindSelfCacheKey, BindSelfCacheValue]]
67+
5068
# This contains protocol dependencies generated after running a full build,
5169
# or after an update. These dependencies are special because:
5270
# * They are a global property of the program; i.e. some dependencies for imported
@@ -119,6 +137,7 @@ def __init__(self) -> None:
119137
self.infer_unions = False
120138
self.infer_polymorphic = False
121139
self.keep_unions = False
140+
self.bind_self_cache = {}
122141

123142
def is_assumed_subtype(self, left: Type, right: Type) -> bool:
124143
for l, r in reversed(self._assuming):
@@ -331,4 +350,5 @@ def reset_global_state() -> None:
331350
"""
332351
type_state.reset_all_subtype_caches()
333352
type_state.reset_protocol_deps()
353+
type_state.bind_self_cache.clear()
334354
TypeVarId.next_raw_id = 1

0 commit comments

Comments
 (0)