5757 LiteralType ,
5858 NoneType ,
5959 Overloaded ,
60+ Parameters ,
6061 ParamSpecType ,
6162 PartialType ,
6263 ProperType ,
@@ -792,6 +793,33 @@ def analyze_var(
792793 else :
793794 call_type = typ
794795
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
795823 if isinstance (call_type , FunctionLike ) and not call_type .is_type_obj ():
796824 if mx .is_lvalue :
797825 if var .is_property :
@@ -803,7 +831,7 @@ def analyze_var(
803831 if not var .is_staticmethod :
804832 # Class-level function objects and classmethods become bound methods:
805833 # the former to the instance, the latter to the class.
806- functype : FunctionLike = call_type
834+ functype = call_type
807835 # Use meet to narrow original_type to the dispatched type.
808836 # For example, assume
809837 # * A.f: Callable[[A1], None] where A1 <: A (maybe A1 == A)
@@ -1061,6 +1089,30 @@ def analyze_class_attribute_access(
10611089 isinstance (node .node , FuncBase ) and node .node .is_static
10621090 )
10631091 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 )
10641116 if isinstance (t , FunctionLike ) and is_classmethod :
10651117 t = check_self_arg (t , mx .self_type , False , mx .context , name , mx .msg )
10661118 result = add_class_tvars (
@@ -1348,3 +1400,30 @@ def is_valid_constructor(n: SymbolNode | None) -> bool:
13481400 if isinstance (n , Decorator ):
13491401 return isinstance (get_proper_type (n .type ), FunctionLike )
13501402 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