57
57
LiteralType ,
58
58
NoneType ,
59
59
Overloaded ,
60
+ Parameters ,
60
61
ParamSpecType ,
61
62
PartialType ,
62
63
ProperType ,
@@ -782,6 +783,33 @@ def analyze_var(
782
783
else :
783
784
call_type = typ
784
785
786
+ if isinstance (call_type , Instance ) and any (
787
+ isinstance (arg , Parameters ) for arg in call_type .args
788
+ ):
789
+ args : list [Type ] = []
790
+ for arg in call_type .args :
791
+ if not isinstance (arg , Parameters ):
792
+ args .append (arg )
793
+ continue
794
+ c = callable_type_from_parameters (arg , mx .chk .named_type ("builtins.function" ))
795
+ if not var .is_staticmethod :
796
+ functype : FunctionLike = c
797
+ dispatched_type = meet .meet_types (mx .original_type , itype )
798
+ signature = freshen_all_functions_type_vars (functype )
799
+ bound = get_proper_type (expand_self_type (var , signature , mx .original_type ))
800
+ assert isinstance (bound , FunctionLike )
801
+ signature = bound
802
+ signature = check_self_arg (
803
+ signature , dispatched_type , var .is_classmethod , mx .context , name , mx .msg
804
+ )
805
+ signature = bind_self (signature , mx .self_type , var .is_classmethod )
806
+ expanded_signature = expand_type_by_instance (signature , itype )
807
+ freeze_all_type_vars (expanded_signature )
808
+ assert isinstance (expanded_signature , CallableType )
809
+ arg = update_parameters_from_signature (arg , expanded_signature )
810
+ args .append (arg )
811
+ call_type = call_type .copy_modified (args = args )
812
+ result = call_type
785
813
if isinstance (call_type , FunctionLike ) and not call_type .is_type_obj ():
786
814
if mx .is_lvalue :
787
815
if var .is_property :
@@ -793,7 +821,7 @@ def analyze_var(
793
821
if not var .is_staticmethod :
794
822
# Class-level function objects and classmethods become bound methods:
795
823
# the former to the instance, the latter to the class.
796
- functype : FunctionLike = call_type
824
+ functype = call_type
797
825
# Use meet to narrow original_type to the dispatched type.
798
826
# For example, assume
799
827
# * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
@@ -1094,6 +1122,30 @@ def analyze_class_attribute_access(
1094
1122
isinstance (node .node , FuncBase ) and node .node .is_static
1095
1123
)
1096
1124
t = get_proper_type (t )
1125
+ if isinstance (t , Instance ) and any (isinstance (arg , Parameters ) for arg in t .args ):
1126
+ args : list [Type ] = []
1127
+ for arg in t .args :
1128
+ if not isinstance (arg , Parameters ):
1129
+ args .append (arg )
1130
+ continue
1131
+ c : FunctionLike = callable_type_from_parameters (
1132
+ arg , mx .chk .named_type ("builtins.function" )
1133
+ )
1134
+ if is_classmethod :
1135
+ c = check_self_arg (c , mx .self_type , False , mx .context , name , mx .msg )
1136
+ res = add_class_tvars (
1137
+ c ,
1138
+ isuper ,
1139
+ is_classmethod ,
1140
+ is_staticmethod ,
1141
+ mx .self_type ,
1142
+ original_vars = original_vars ,
1143
+ )
1144
+ signature = get_proper_type (res )
1145
+ assert isinstance (signature , CallableType )
1146
+ arg = update_parameters_from_signature (arg , signature )
1147
+ args .append (arg )
1148
+ t = t .copy_modified (args = args )
1097
1149
if isinstance (t , FunctionLike ) and is_classmethod :
1098
1150
t = check_self_arg (t , mx .self_type , False , mx .context , name , mx .msg )
1099
1151
result = add_class_tvars (
@@ -1392,3 +1444,30 @@ def is_valid_constructor(n: SymbolNode | None) -> bool:
1392
1444
if isinstance (n , Decorator ):
1393
1445
return isinstance (get_proper_type (n .type ), FunctionLike )
1394
1446
return False
1447
+
1448
+
1449
+ def callable_type_from_parameters (
1450
+ param : Parameters , fallback : Instance , ret_type : Type | None = None
1451
+ ) -> CallableType :
1452
+ """Create CallableType from Parameters."""
1453
+ return CallableType (
1454
+ arg_types = param .arg_types ,
1455
+ arg_kinds = param .arg_kinds ,
1456
+ arg_names = param .arg_names ,
1457
+ ret_type = ret_type if ret_type is not None else NoneType (),
1458
+ fallback = fallback ,
1459
+ variables = param .variables ,
1460
+ imprecise_arg_kinds = param .imprecise_arg_kinds ,
1461
+ )
1462
+
1463
+
1464
+ def update_parameters_from_signature (param : Parameters , signature : CallableType ) -> Parameters :
1465
+ """Update Parameters from signature."""
1466
+ return param .copy_modified (
1467
+ arg_types = signature .arg_types ,
1468
+ arg_kinds = signature .arg_kinds ,
1469
+ arg_names = signature .arg_names ,
1470
+ is_ellipsis_args = signature .is_ellipsis_args ,
1471
+ variables = signature .variables ,
1472
+ imprecise_arg_kinds = signature .imprecise_arg_kinds ,
1473
+ )
0 commit comments