7
7
CallableType , Type , TypeVisitor , UnboundType , AnyType , NoneType , TypeVarType , Instance ,
8
8
TupleType , TypedDictType , UnionType , Overloaded , ErasedType , PartialType , DeletedType ,
9
9
UninhabitedType , TypeType , TypeVarId , TypeQuery , is_named_instance , TypeOfAny , LiteralType ,
10
- ProperType , get_proper_type , TypeAliasType , is_union_with_any
10
+ ProperType , ParamSpecType , get_proper_type , TypeAliasType , is_union_with_any ,
11
+ callable_with_ellipsis
11
12
)
12
13
from mypy .maptype import map_instance_to_supertype
13
14
import mypy .subtypes
@@ -398,6 +399,10 @@ def visit_type_var(self, template: TypeVarType) -> List[Constraint]:
398
399
assert False , ("Unexpected TypeVarType in ConstraintBuilderVisitor"
399
400
" (should have been handled in infer_constraints)" )
400
401
402
+ def visit_param_spec (self , template : ParamSpecType ) -> List [Constraint ]:
403
+ # Can't infer ParamSpecs from component values (only via Callable[P, T]).
404
+ return []
405
+
401
406
# Non-leaf types
402
407
403
408
def visit_instance (self , template : Instance ) -> List [Constraint ]:
@@ -438,14 +443,16 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
438
443
# N.B: We use zip instead of indexing because the lengths might have
439
444
# mismatches during daemon reprocessing.
440
445
for tvar , mapped_arg , instance_arg in zip (tvars , mapped .args , instance .args ):
441
- # The constraints for generic type parameters depend on variance.
442
- # Include constraints from both directions if invariant.
443
- if tvar .variance != CONTRAVARIANT :
444
- res .extend (infer_constraints (
445
- mapped_arg , instance_arg , self .direction ))
446
- if tvar .variance != COVARIANT :
447
- res .extend (infer_constraints (
448
- mapped_arg , instance_arg , neg_op (self .direction )))
446
+ # TODO: ParamSpecType
447
+ if isinstance (tvar , TypeVarType ):
448
+ # The constraints for generic type parameters depend on variance.
449
+ # Include constraints from both directions if invariant.
450
+ if tvar .variance != CONTRAVARIANT :
451
+ res .extend (infer_constraints (
452
+ mapped_arg , instance_arg , self .direction ))
453
+ if tvar .variance != COVARIANT :
454
+ res .extend (infer_constraints (
455
+ mapped_arg , instance_arg , neg_op (self .direction )))
449
456
return res
450
457
elif (self .direction == SUPERTYPE_OF and
451
458
instance .type .has_base (template .type .fullname )):
@@ -454,14 +461,16 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
454
461
# N.B: We use zip instead of indexing because the lengths might have
455
462
# mismatches during daemon reprocessing.
456
463
for tvar , mapped_arg , template_arg in zip (tvars , mapped .args , template .args ):
457
- # The constraints for generic type parameters depend on variance.
458
- # Include constraints from both directions if invariant.
459
- if tvar .variance != CONTRAVARIANT :
460
- res .extend (infer_constraints (
461
- template_arg , mapped_arg , self .direction ))
462
- if tvar .variance != COVARIANT :
463
- res .extend (infer_constraints (
464
- template_arg , mapped_arg , neg_op (self .direction )))
464
+ # TODO: ParamSpecType
465
+ if isinstance (tvar , TypeVarType ):
466
+ # The constraints for generic type parameters depend on variance.
467
+ # Include constraints from both directions if invariant.
468
+ if tvar .variance != CONTRAVARIANT :
469
+ res .extend (infer_constraints (
470
+ template_arg , mapped_arg , self .direction ))
471
+ if tvar .variance != COVARIANT :
472
+ res .extend (infer_constraints (
473
+ template_arg , mapped_arg , neg_op (self .direction )))
465
474
return res
466
475
if (template .type .is_protocol and self .direction == SUPERTYPE_OF and
467
476
# We avoid infinite recursion for structural subtypes by checking
@@ -536,32 +545,48 @@ def infer_constraints_from_protocol_members(self,
536
545
537
546
def visit_callable_type (self , template : CallableType ) -> List [Constraint ]:
538
547
if isinstance (self .actual , CallableType ):
539
- cactual = self .actual
540
- # FIX verify argument counts
541
- # FIX what if one of the functions is generic
542
548
res : List [Constraint ] = []
549
+ cactual = self .actual
550
+ param_spec = template .param_spec ()
551
+ if param_spec is None :
552
+ # FIX verify argument counts
553
+ # FIX what if one of the functions is generic
554
+
555
+ # We can't infer constraints from arguments if the template is Callable[..., T]
556
+ # (with literal '...').
557
+ if not template .is_ellipsis_args :
558
+ # The lengths should match, but don't crash (it will error elsewhere).
559
+ for t , a in zip (template .arg_types , cactual .arg_types ):
560
+ # Negate direction due to function argument type contravariance.
561
+ res .extend (infer_constraints (t , a , neg_op (self .direction )))
562
+ else :
563
+ # TODO: Direction
564
+ # TODO: Deal with arguments that come before param spec ones?
565
+ res .append (Constraint (param_spec .id ,
566
+ SUBTYPE_OF ,
567
+ cactual .copy_modified (ret_type = NoneType ())))
543
568
544
- # We can't infer constraints from arguments if the template is Callable[..., T] (with
545
- # literal '...').
546
- if not template .is_ellipsis_args :
547
- # The lengths should match, but don't crash (it will error elsewhere).
548
- for t , a in zip (template .arg_types , cactual .arg_types ):
549
- # Negate direction due to function argument type contravariance.
550
- res .extend (infer_constraints (t , a , neg_op (self .direction )))
551
569
template_ret_type , cactual_ret_type = template .ret_type , cactual .ret_type
552
570
if template .type_guard is not None :
553
571
template_ret_type = template .type_guard
554
572
if cactual .type_guard is not None :
555
573
cactual_ret_type = cactual .type_guard
574
+
556
575
res .extend (infer_constraints (template_ret_type , cactual_ret_type ,
557
576
self .direction ))
558
577
return res
559
578
elif isinstance (self .actual , AnyType ):
560
- # FIX what if generic
561
- res = self .infer_against_any (template .arg_types , self .actual )
579
+ param_spec = template .param_spec ()
562
580
any_type = AnyType (TypeOfAny .from_another_any , source_any = self .actual )
563
- res .extend (infer_constraints (template .ret_type , any_type , self .direction ))
564
- return res
581
+ if param_spec is None :
582
+ # FIX what if generic
583
+ res = self .infer_against_any (template .arg_types , self .actual )
584
+ res .extend (infer_constraints (template .ret_type , any_type , self .direction ))
585
+ return res
586
+ else :
587
+ return [Constraint (param_spec .id ,
588
+ SUBTYPE_OF ,
589
+ callable_with_ellipsis (any_type , any_type , template .fallback ))]
565
590
elif isinstance (self .actual , Overloaded ):
566
591
return self .infer_against_overloaded (self .actual , template )
567
592
elif isinstance (self .actual , TypeType ):
0 commit comments