@@ -303,7 +303,7 @@ class B(A): pass
303
303
return cast (F , func )
304
304
self_param_type = get_proper_type (func .arg_types [0 ])
305
305
306
- variables : Sequence [TypeVarLikeType ] = []
306
+ variables : Sequence [TypeVarLikeType ]
307
307
if func .variables and supported_self_type (self_param_type ):
308
308
from mypy .infer import infer_type_arguments
309
309
@@ -312,46 +312,40 @@ class B(A): pass
312
312
original_type = erase_to_bound (self_param_type )
313
313
original_type = get_proper_type (original_type )
314
314
315
- all_ids = func .type_var_ids ()
315
+ # Find which of method type variables appear in the type of "self".
316
+ self_ids = {tv .id for tv in get_all_type_vars (self_param_type )}
317
+ self_vars = [tv for tv in func .variables if tv .id in self_ids ]
318
+
319
+ # Solve for these type arguments using the actual class or instance type.
316
320
typeargs = infer_type_arguments (
317
- func . variables , self_param_type , original_type , is_supertype = True
321
+ self_vars , self_param_type , original_type , is_supertype = True
318
322
)
319
323
if (
320
324
is_classmethod
321
- # TODO: why do we need the extra guards here?
322
325
and any (isinstance (get_proper_type (t ), UninhabitedType ) for t in typeargs )
323
326
and isinstance (original_type , (Instance , TypeVarType , TupleType ))
324
327
):
325
- # In case we call a classmethod through an instance x, fallback to type(x)
328
+ # In case we call a classmethod through an instance x, fallback to type(x).
326
329
typeargs = infer_type_arguments (
327
- func . variables , self_param_type , TypeType (original_type ), is_supertype = True
330
+ self_vars , self_param_type , TypeType (original_type ), is_supertype = True
328
331
)
329
332
330
- ids = [tid for tid in all_ids if any (tid == t .id for t in get_type_vars (self_param_type ))]
331
-
332
- # Technically, some constrains might be unsolvable, make them <nothing>.
333
+ # Update the method signature with the solutions found.
334
+ # Technically, some constraints might be unsolvable, make them <nothing>.
333
335
to_apply = [t if t is not None else UninhabitedType () for t in typeargs ]
334
-
335
- def expand (target : Type ) -> Type :
336
- return expand_type (target , {id : to_apply [all_ids .index (id )] for id in ids })
337
-
338
- arg_types = [expand (x ) for x in func .arg_types [1 :]]
339
- ret_type = expand (func .ret_type )
340
- variables = [v for v in func .variables if v .id not in ids ]
336
+ func = expand_type (func , {tv .id : arg for tv , arg in zip (self_vars , to_apply )})
337
+ variables = [v for v in func .variables if v not in self_vars ]
341
338
else :
342
- arg_types = func .arg_types [1 :]
343
- ret_type = func .ret_type
344
339
variables = func .variables
345
340
346
341
original_type = get_proper_type (original_type )
347
342
if isinstance (original_type , CallableType ) and original_type .is_type_obj ():
348
343
original_type = TypeType .make_normalized (original_type .ret_type )
349
344
res = func .copy_modified (
350
- arg_types = arg_types ,
345
+ arg_types = func . arg_types [ 1 :] ,
351
346
arg_kinds = func .arg_kinds [1 :],
352
347
arg_names = func .arg_names [1 :],
353
348
variables = variables ,
354
- ret_type = ret_type ,
355
349
bound_args = [original_type ],
356
350
)
357
351
return cast (F , res )
0 commit comments