77 CallableType , Type , TypeVisitor , UnboundType , AnyType , NoneType , TypeVarType , Instance ,
88 TupleType , TypedDictType , UnionType , Overloaded , ErasedType , PartialType , DeletedType ,
99 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
1112)
1213from mypy .maptype import map_instance_to_supertype
1314import mypy .subtypes
@@ -398,6 +399,10 @@ def visit_type_var(self, template: TypeVarType) -> List[Constraint]:
398399 assert False , ("Unexpected TypeVarType in ConstraintBuilderVisitor"
399400 " (should have been handled in infer_constraints)" )
400401
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+
401406 # Non-leaf types
402407
403408 def visit_instance (self , template : Instance ) -> List [Constraint ]:
@@ -438,14 +443,16 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
438443 # N.B: We use zip instead of indexing because the lengths might have
439444 # mismatches during daemon reprocessing.
440445 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 )))
449456 return res
450457 elif (self .direction == SUPERTYPE_OF and
451458 instance .type .has_base (template .type .fullname )):
@@ -454,14 +461,16 @@ def visit_instance(self, template: Instance) -> List[Constraint]:
454461 # N.B: We use zip instead of indexing because the lengths might have
455462 # mismatches during daemon reprocessing.
456463 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 )))
465474 return res
466475 if (template .type .is_protocol and self .direction == SUPERTYPE_OF and
467476 # We avoid infinite recursion for structural subtypes by checking
@@ -536,32 +545,48 @@ def infer_constraints_from_protocol_members(self,
536545
537546 def visit_callable_type (self , template : CallableType ) -> List [Constraint ]:
538547 if isinstance (self .actual , CallableType ):
539- cactual = self .actual
540- # FIX verify argument counts
541- # FIX what if one of the functions is generic
542548 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 ())))
543568
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 )))
551569 template_ret_type , cactual_ret_type = template .ret_type , cactual .ret_type
552570 if template .type_guard is not None :
553571 template_ret_type = template .type_guard
554572 if cactual .type_guard is not None :
555573 cactual_ret_type = cactual .type_guard
574+
556575 res .extend (infer_constraints (template_ret_type , cactual_ret_type ,
557576 self .direction ))
558577 return res
559578 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 ()
562580 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 ))]
565590 elif isinstance (self .actual , Overloaded ):
566591 return self .infer_against_overloaded (self .actual , template )
567592 elif isinstance (self .actual , TypeType ):
0 commit comments