11
11
from collections .abc import Iterable , Sequence
12
12
from typing import Any , Callable , TypeVar , cast
13
13
14
+ from mypy .checker_state import checker_state
14
15
from mypy .copytype import copy_type
15
16
from mypy .expandtype import expand_type , expand_type_by_instance
16
17
from mypy .maptype import map_instance_to_supertype
@@ -145,6 +146,15 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
145
146
where ... are argument types for the __init__/__new__ method (without the self
146
147
argument). Also, the fallback type will be 'type' instead of 'function'.
147
148
"""
149
+ allow_cache = (
150
+ checker_state .type_checker is not None
151
+ and checker_state .type_checker .allow_constructor_cache
152
+ )
153
+
154
+ if info .type_object_type is not None :
155
+ if allow_cache :
156
+ return info .type_object_type
157
+ info .type_object_type = None
148
158
149
159
# We take the type from whichever of __init__ and __new__ is first
150
160
# in the MRO, preferring __init__ if there is a tie.
@@ -167,7 +177,15 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
167
177
init_index = info .mro .index (init_method .node .info )
168
178
new_index = info .mro .index (new_method .node .info )
169
179
170
- fallback = info .metaclass_type or named_type ("builtins.type" )
180
+ if info .metaclass_type is not None :
181
+ fallback = info .metaclass_type
182
+ elif checker_state .type_checker :
183
+ # Prefer direct call when it is available. It is faster, and,
184
+ # unfortunately, some callers provide bogus callback.
185
+ fallback = checker_state .type_checker .named_type ("builtins.type" )
186
+ else :
187
+ fallback = named_type ("builtins.type" )
188
+
171
189
if init_index < new_index :
172
190
method : FuncBase | Decorator = init_method .node
173
191
is_new = False
@@ -189,7 +207,10 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
189
207
is_bound = True ,
190
208
fallback = named_type ("builtins.function" ),
191
209
)
192
- return class_callable (sig , info , fallback , None , is_new = False )
210
+ result : FunctionLike = class_callable (sig , info , fallback , None , is_new = False )
211
+ if allow_cache :
212
+ info .type_object_type = result
213
+ return result
193
214
194
215
# Otherwise prefer __init__ in a tie. It isn't clear that this
195
216
# is the right thing, but __new__ caused problems with
@@ -199,12 +220,19 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
199
220
# Construct callable type based on signature of __init__. Adjust
200
221
# return type and insert type arguments.
201
222
if isinstance (method , FuncBase ):
223
+ if isinstance (method , OverloadedFuncDef ) and not method .type :
224
+ # Do not cache if the type is not ready. Same logic for decorators is
225
+ # achieved in early return above because is_valid_constructor() is False.
226
+ allow_cache = False
202
227
t = function_type (method , fallback )
203
228
else :
204
229
assert isinstance (method .type , ProperType )
205
230
assert isinstance (method .type , FunctionLike ) # is_valid_constructor() ensures this
206
231
t = method .type
207
- return type_object_type_from_function (t , info , method .info , fallback , is_new )
232
+ result = type_object_type_from_function (t , info , method .info , fallback , is_new )
233
+ if allow_cache :
234
+ info .type_object_type = result
235
+ return result
208
236
209
237
210
238
def is_valid_constructor (n : SymbolNode | None ) -> bool :
@@ -865,8 +893,8 @@ def function_type(func: FuncBase, fallback: Instance) -> FunctionLike:
865
893
if isinstance (func , FuncItem ):
866
894
return callable_type (func , fallback )
867
895
else :
868
- # Broken overloads can have self. type set to None .
869
- # TODO: should we instead always set the type in semantic analyzer?
896
+ # Either a broken overload, or decorated overload type is not ready .
897
+ # TODO: make sure the caller defers if possible.
870
898
assert isinstance (func , OverloadedFuncDef )
871
899
any_type = AnyType (TypeOfAny .from_error )
872
900
dummy = CallableType (
@@ -1254,6 +1282,8 @@ def get_protocol_member(
1254
1282
if member == "__call__" and class_obj :
1255
1283
# Special case: class objects always have __call__ that is just the constructor.
1256
1284
1285
+ # TODO: this is wrong, it creates callables that are not recognized as type objects.
1286
+ # Long-term, we should probably get rid of this callback argument altogether.
1257
1287
def named_type (fullname : str ) -> Instance :
1258
1288
return Instance (left .type .mro [- 1 ], [])
1259
1289
0 commit comments