57
57
LiteralType ,
58
58
NoneType ,
59
59
Overloaded ,
60
+ Parameters ,
60
61
ParamSpecType ,
61
62
PartialType ,
62
63
ProperType ,
@@ -792,6 +793,33 @@ def analyze_var(
792
793
else :
793
794
call_type = typ
794
795
796
+ if isinstance (call_type , Instance ) and any (
797
+ isinstance (arg , Parameters ) for arg in call_type .args
798
+ ):
799
+ args : list [Type ] = []
800
+ for arg in call_type .args :
801
+ if not isinstance (arg , Parameters ):
802
+ args .append (arg )
803
+ continue
804
+ c = callable_type_from_parameters (arg , mx .chk .named_type ("builtins.function" ))
805
+ if not var .is_staticmethod :
806
+ functype : FunctionLike = c
807
+ dispatched_type = meet .meet_types (mx .original_type , itype )
808
+ signature = freshen_all_functions_type_vars (functype )
809
+ bound = get_proper_type (expand_self_type (var , signature , mx .original_type ))
810
+ assert isinstance (bound , FunctionLike )
811
+ signature = bound
812
+ signature = check_self_arg (
813
+ signature , dispatched_type , var .is_classmethod , mx .context , name , mx .msg
814
+ )
815
+ signature = bind_self (signature , mx .self_type , var .is_classmethod )
816
+ expanded_signature = expand_type_by_instance (signature , itype )
817
+ freeze_all_type_vars (expanded_signature )
818
+ assert isinstance (expanded_signature , CallableType )
819
+ arg = update_parameters_from_signature (arg , expanded_signature )
820
+ args .append (arg )
821
+ call_type = call_type .copy_modified (args = args )
822
+ result = call_type
795
823
if isinstance (call_type , FunctionLike ) and not call_type .is_type_obj ():
796
824
if mx .is_lvalue :
797
825
if var .is_property :
@@ -803,7 +831,7 @@ def analyze_var(
803
831
if not var .is_staticmethod :
804
832
# Class-level function objects and classmethods become bound methods:
805
833
# the former to the instance, the latter to the class.
806
- functype : FunctionLike = call_type
834
+ functype = call_type
807
835
# Use meet to narrow original_type to the dispatched type.
808
836
# For example, assume
809
837
# * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
@@ -1061,6 +1089,30 @@ def analyze_class_attribute_access(
1061
1089
isinstance (node .node , FuncBase ) and node .node .is_static
1062
1090
)
1063
1091
t = get_proper_type (t )
1092
+ if isinstance (t , Instance ) and any (isinstance (arg , Parameters ) for arg in t .args ):
1093
+ args : list [Type ] = []
1094
+ for arg in t .args :
1095
+ if not isinstance (arg , Parameters ):
1096
+ args .append (arg )
1097
+ continue
1098
+ c : FunctionLike = callable_type_from_parameters (
1099
+ arg , mx .chk .named_type ("builtins.function" )
1100
+ )
1101
+ if is_classmethod :
1102
+ c = check_self_arg (c , mx .self_type , False , mx .context , name , mx .msg )
1103
+ res = add_class_tvars (
1104
+ c ,
1105
+ isuper ,
1106
+ is_classmethod ,
1107
+ is_staticmethod ,
1108
+ mx .self_type ,
1109
+ original_vars = original_vars ,
1110
+ )
1111
+ signature = get_proper_type (res )
1112
+ assert isinstance (signature , CallableType )
1113
+ arg = update_parameters_from_signature (arg , signature )
1114
+ args .append (arg )
1115
+ t = t .copy_modified (args = args )
1064
1116
if isinstance (t , FunctionLike ) and is_classmethod :
1065
1117
t = check_self_arg (t , mx .self_type , False , mx .context , name , mx .msg )
1066
1118
result = add_class_tvars (
@@ -1348,3 +1400,30 @@ def is_valid_constructor(n: SymbolNode | None) -> bool:
1348
1400
if isinstance (n , Decorator ):
1349
1401
return isinstance (get_proper_type (n .type ), FunctionLike )
1350
1402
return False
1403
+
1404
+
1405
+ def callable_type_from_parameters (
1406
+ param : Parameters , fallback : Instance , ret_type : Type | None = None
1407
+ ) -> CallableType :
1408
+ """Create CallableType from Parameters."""
1409
+ return CallableType (
1410
+ arg_types = param .arg_types ,
1411
+ arg_kinds = param .arg_kinds ,
1412
+ arg_names = param .arg_names ,
1413
+ ret_type = ret_type if ret_type is not None else NoneType (),
1414
+ fallback = fallback ,
1415
+ variables = param .variables ,
1416
+ imprecise_arg_kinds = param .imprecise_arg_kinds ,
1417
+ )
1418
+
1419
+
1420
+ def update_parameters_from_signature (param : Parameters , signature : CallableType ) -> Parameters :
1421
+ """Update Parameters from signature."""
1422
+ return param .copy_modified (
1423
+ arg_types = signature .arg_types ,
1424
+ arg_kinds = signature .arg_kinds ,
1425
+ arg_names = signature .arg_names ,
1426
+ is_ellipsis_args = signature .is_ellipsis_args ,
1427
+ variables = signature .variables ,
1428
+ imprecise_arg_kinds = signature .imprecise_arg_kinds ,
1429
+ )
0 commit comments