@@ -794,8 +794,10 @@ struct DynamicCallPattern {
794794 module_arg_index : Option < usize > ,
795795 /// Index of the target function argument
796796 function_arg_index : usize ,
797- /// Index of the arguments list
797+ /// Index of the arguments list or arity argument
798798 args_list_index : usize ,
799+ /// Whether to extract arity directly from an integer argument (true) or from list length (false)
800+ direct_arity : bool ,
799801}
800802
801803static DYNAMIC_CALL_PATTERNS : & [ DynamicCallPattern ] = & [
@@ -807,6 +809,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
807809 module_arg_index : None ,
808810 function_arg_index : 0 ,
809811 args_list_index : 1 ,
812+ direct_arity : false ,
810813 } ,
811814 // apply/3 (implicit erlang:apply/3) - apply(Module, Function, Args)
812815 DynamicCallPattern {
@@ -816,6 +819,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
816819 module_arg_index : Some ( 0 ) ,
817820 function_arg_index : 1 ,
818821 args_list_index : 2 ,
822+ direct_arity : false ,
819823 } ,
820824 // erlang:apply/2 (explicit) - erlang:apply(Fun, Args)
821825 DynamicCallPattern {
@@ -825,6 +829,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
825829 module_arg_index : None ,
826830 function_arg_index : 0 ,
827831 args_list_index : 1 ,
832+ direct_arity : false ,
828833 } ,
829834 // erlang:apply/3 (explicit) - erlang:apply(Module, Function, Args)
830835 DynamicCallPattern {
@@ -834,6 +839,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
834839 module_arg_index : Some ( 0 ) ,
835840 function_arg_index : 1 ,
836841 args_list_index : 2 ,
842+ direct_arity : false ,
837843 } ,
838844 // rpc:call/4 - rpc:call(Node, Module, Function, Args)
839845 DynamicCallPattern {
@@ -843,6 +849,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
843849 module_arg_index : Some ( 1 ) ,
844850 function_arg_index : 2 ,
845851 args_list_index : 3 ,
852+ direct_arity : false ,
846853 } ,
847854 // rpc:call/5 - rpc:call(Node, Module, Function, Args, Timeout)
848855 DynamicCallPattern {
@@ -852,6 +859,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
852859 module_arg_index : Some ( 1 ) ,
853860 function_arg_index : 2 ,
854861 args_list_index : 3 ,
862+ direct_arity : false ,
855863 } ,
856864 // rpc:async_call/4 - rpc:async_call(Node, Module, Function, Args)
857865 DynamicCallPattern {
@@ -861,6 +869,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
861869 module_arg_index : Some ( 1 ) ,
862870 function_arg_index : 2 ,
863871 args_list_index : 3 ,
872+ direct_arity : false ,
864873 } ,
865874 // rpc:cast/4 - rpc:cast(Node, Module, Function, Args)
866875 DynamicCallPattern {
@@ -870,6 +879,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
870879 module_arg_index : Some ( 1 ) ,
871880 function_arg_index : 2 ,
872881 args_list_index : 3 ,
882+ direct_arity : false ,
873883 } ,
874884 // rpc:multicall/3 - rpc:multicall(Module, Function, Args)
875885 DynamicCallPattern {
@@ -879,6 +889,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
879889 module_arg_index : Some ( 0 ) ,
880890 function_arg_index : 1 ,
881891 args_list_index : 2 ,
892+ direct_arity : false ,
882893 } ,
883894 // rpc:multicall/4 - rpc:multicall(Module, Function, Args, Timeout)
884895 DynamicCallPattern {
@@ -888,6 +899,7 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
888899 module_arg_index : Some ( 0 ) ,
889900 function_arg_index : 1 ,
890901 args_list_index : 2 ,
902+ direct_arity : false ,
891903 } ,
892904 // rpc:multicall/5 - rpc:multicall(Nodes, Module, Function, Args, Timeout)
893905 DynamicCallPattern {
@@ -897,6 +909,247 @@ static DYNAMIC_CALL_PATTERNS: &[DynamicCallPattern] = &[
897909 module_arg_index : Some ( 1 ) ,
898910 function_arg_index : 2 ,
899911 args_list_index : 3 ,
912+ direct_arity : false ,
913+ } ,
914+ // function_exported/3 (implicit erlang:function_exported/3) - function_exported(Module, Function, Arity)
915+ DynamicCallPattern {
916+ module : None ,
917+ function : "function_exported" ,
918+ arity : 3 ,
919+ module_arg_index : Some ( 0 ) ,
920+ function_arg_index : 1 ,
921+ args_list_index : 2 ,
922+ direct_arity : true ,
923+ } ,
924+ // erlang:function_exported/3 (explicit) - erlang:function_exported(Module, Function, Arity)
925+ DynamicCallPattern {
926+ module : Some ( "erlang" ) ,
927+ function : "function_exported" ,
928+ arity : 3 ,
929+ module_arg_index : Some ( 0 ) ,
930+ function_arg_index : 1 ,
931+ args_list_index : 2 ,
932+ direct_arity : true ,
933+ } ,
934+ // is_builtin/3 (implicit erlang:is_builtin/3) - is_builtin(Module, Function, Arity)
935+ DynamicCallPattern {
936+ module : None ,
937+ function : "is_builtin" ,
938+ arity : 3 ,
939+ module_arg_index : Some ( 0 ) ,
940+ function_arg_index : 1 ,
941+ args_list_index : 2 ,
942+ direct_arity : true ,
943+ } ,
944+ // erlang:is_builtin/3 (explicit) - erlang:is_builtin(Module, Function, Arity)
945+ DynamicCallPattern {
946+ module : Some ( "erlang" ) ,
947+ function : "is_builtin" ,
948+ arity : 3 ,
949+ module_arg_index : Some ( 0 ) ,
950+ function_arg_index : 1 ,
951+ args_list_index : 2 ,
952+ direct_arity : true ,
953+ } ,
954+ // hibernate/3 (implicit erlang:hibernate/3) - hibernate(Module, Function, Args)
955+ DynamicCallPattern {
956+ module : None ,
957+ function : "hibernate" ,
958+ arity : 3 ,
959+ module_arg_index : Some ( 0 ) ,
960+ function_arg_index : 1 ,
961+ args_list_index : 2 ,
962+ direct_arity : false ,
963+ } ,
964+ // erlang:hibernate/3 (explicit) - erlang:hibernate(Module, Function, Args)
965+ DynamicCallPattern {
966+ module : Some ( "erlang" ) ,
967+ function : "hibernate" ,
968+ arity : 3 ,
969+ module_arg_index : Some ( 0 ) ,
970+ function_arg_index : 1 ,
971+ args_list_index : 2 ,
972+ direct_arity : false ,
973+ } ,
974+ // spawn/3 (implicit erlang:spawn/3) - spawn(Module, Function, Args)
975+ DynamicCallPattern {
976+ module : None ,
977+ function : "spawn" ,
978+ arity : 3 ,
979+ module_arg_index : Some ( 0 ) ,
980+ function_arg_index : 1 ,
981+ args_list_index : 2 ,
982+ direct_arity : false ,
983+ } ,
984+ // erlang:spawn/3 (explicit) - erlang:spawn(Module, Function, Args)
985+ DynamicCallPattern {
986+ module : Some ( "erlang" ) ,
987+ function : "spawn" ,
988+ arity : 3 ,
989+ module_arg_index : Some ( 0 ) ,
990+ function_arg_index : 1 ,
991+ args_list_index : 2 ,
992+ direct_arity : false ,
993+ } ,
994+ // spawn/4 (implicit erlang:spawn/4) - spawn(Node, Module, Function, Args)
995+ DynamicCallPattern {
996+ module : None ,
997+ function : "spawn" ,
998+ arity : 4 ,
999+ module_arg_index : Some ( 1 ) ,
1000+ function_arg_index : 2 ,
1001+ args_list_index : 3 ,
1002+ direct_arity : false ,
1003+ } ,
1004+ // erlang:spawn/4 (explicit) - erlang:spawn(Node, Module, Function, Args)
1005+ DynamicCallPattern {
1006+ module : Some ( "erlang" ) ,
1007+ function : "spawn" ,
1008+ arity : 4 ,
1009+ module_arg_index : Some ( 1 ) ,
1010+ function_arg_index : 2 ,
1011+ args_list_index : 3 ,
1012+ direct_arity : false ,
1013+ } ,
1014+ // spawn_link/3 (implicit erlang:spawn_link/3) - spawn_link(Module, Function, Args)
1015+ DynamicCallPattern {
1016+ module : None ,
1017+ function : "spawn_link" ,
1018+ arity : 3 ,
1019+ module_arg_index : Some ( 0 ) ,
1020+ function_arg_index : 1 ,
1021+ args_list_index : 2 ,
1022+ direct_arity : false ,
1023+ } ,
1024+ // erlang:spawn_link/3 (explicit) - erlang:spawn_link(Module, Function, Args)
1025+ DynamicCallPattern {
1026+ module : Some ( "erlang" ) ,
1027+ function : "spawn_link" ,
1028+ arity : 3 ,
1029+ module_arg_index : Some ( 0 ) ,
1030+ function_arg_index : 1 ,
1031+ args_list_index : 2 ,
1032+ direct_arity : false ,
1033+ } ,
1034+ // spawn_link/4 (implicit erlang:spawn_link/4) - spawn_link(Node, Module, Function, Args)
1035+ DynamicCallPattern {
1036+ module : None ,
1037+ function : "spawn_link" ,
1038+ arity : 4 ,
1039+ module_arg_index : Some ( 1 ) ,
1040+ function_arg_index : 2 ,
1041+ args_list_index : 3 ,
1042+ direct_arity : false ,
1043+ } ,
1044+ // erlang:spawn_link/4 (explicit) - erlang:spawn_link(Node, Module, Function, Args)
1045+ DynamicCallPattern {
1046+ module : Some ( "erlang" ) ,
1047+ function : "spawn_link" ,
1048+ arity : 4 ,
1049+ module_arg_index : Some ( 1 ) ,
1050+ function_arg_index : 2 ,
1051+ args_list_index : 3 ,
1052+ direct_arity : false ,
1053+ } ,
1054+ // spawn_monitor/3 (implicit erlang:spawn_monitor/3) - spawn_monitor(Module, Function, Args)
1055+ DynamicCallPattern {
1056+ module : None ,
1057+ function : "spawn_monitor" ,
1058+ arity : 3 ,
1059+ module_arg_index : Some ( 0 ) ,
1060+ function_arg_index : 1 ,
1061+ args_list_index : 2 ,
1062+ direct_arity : false ,
1063+ } ,
1064+ // erlang:spawn_monitor/3 (explicit) - erlang:spawn_monitor(Module, Function, Args)
1065+ DynamicCallPattern {
1066+ module : Some ( "erlang" ) ,
1067+ function : "spawn_monitor" ,
1068+ arity : 3 ,
1069+ module_arg_index : Some ( 0 ) ,
1070+ function_arg_index : 1 ,
1071+ args_list_index : 2 ,
1072+ direct_arity : false ,
1073+ } ,
1074+ // spawn_monitor/4 (implicit erlang:spawn_monitor/4) - spawn_monitor(Node, Module, Function, Args)
1075+ DynamicCallPattern {
1076+ module : None ,
1077+ function : "spawn_monitor" ,
1078+ arity : 4 ,
1079+ module_arg_index : Some ( 1 ) ,
1080+ function_arg_index : 2 ,
1081+ args_list_index : 3 ,
1082+ direct_arity : false ,
1083+ } ,
1084+ // erlang:spawn_monitor/4 (explicit) - erlang:spawn_monitor(Node, Module, Function, Args)
1085+ DynamicCallPattern {
1086+ module : Some ( "erlang" ) ,
1087+ function : "spawn_monitor" ,
1088+ arity : 4 ,
1089+ module_arg_index : Some ( 1 ) ,
1090+ function_arg_index : 2 ,
1091+ args_list_index : 3 ,
1092+ direct_arity : false ,
1093+ } ,
1094+ // spawn_opt/4 (implicit erlang:spawn_opt/4) - spawn_opt(Module, Function, Args, Options)
1095+ DynamicCallPattern {
1096+ module : None ,
1097+ function : "spawn_opt" ,
1098+ arity : 4 ,
1099+ module_arg_index : Some ( 0 ) ,
1100+ function_arg_index : 1 ,
1101+ args_list_index : 2 ,
1102+ direct_arity : false ,
1103+ } ,
1104+ // erlang:spawn_opt/4 (explicit) - erlang:spawn_opt(Module, Function, Args, Options)
1105+ DynamicCallPattern {
1106+ module : Some ( "erlang" ) ,
1107+ function : "spawn_opt" ,
1108+ arity : 4 ,
1109+ module_arg_index : Some ( 0 ) ,
1110+ function_arg_index : 1 ,
1111+ args_list_index : 2 ,
1112+ direct_arity : false ,
1113+ } ,
1114+ // spawn_opt/5 (implicit erlang:spawn_opt/5) - spawn_opt(Node, Module, Function, Args, Options)
1115+ DynamicCallPattern {
1116+ module : None ,
1117+ function : "spawn_opt" ,
1118+ arity : 5 ,
1119+ module_arg_index : Some ( 1 ) ,
1120+ function_arg_index : 2 ,
1121+ args_list_index : 3 ,
1122+ direct_arity : false ,
1123+ } ,
1124+ // erlang:spawn_opt/5 (explicit) - erlang:spawn_opt(Node, Module, Function, Args, Options)
1125+ DynamicCallPattern {
1126+ module : Some ( "erlang" ) ,
1127+ function : "spawn_opt" ,
1128+ arity : 5 ,
1129+ module_arg_index : Some ( 1 ) ,
1130+ function_arg_index : 2 ,
1131+ args_list_index : 3 ,
1132+ direct_arity : false ,
1133+ } ,
1134+ // spawn_request/5 (implicit erlang:spawn_request/5) - spawn_request(Node, Module, Function, Args, Options)
1135+ DynamicCallPattern {
1136+ module : None ,
1137+ function : "spawn_request" ,
1138+ arity : 5 ,
1139+ module_arg_index : Some ( 1 ) ,
1140+ function_arg_index : 2 ,
1141+ args_list_index : 3 ,
1142+ direct_arity : false ,
1143+ } ,
1144+ // erlang:spawn_request/5 (explicit) - erlang:spawn_request(Node, Module, Function, Args, Options)
1145+ DynamicCallPattern {
1146+ module : Some ( "erlang" ) ,
1147+ function : "spawn_request" ,
1148+ arity : 5 ,
1149+ module_arg_index : Some ( 1 ) ,
1150+ function_arg_index : 2 ,
1151+ args_list_index : 3 ,
1152+ direct_arity : false ,
9001153 } ,
9011154] ;
9021155
@@ -958,8 +1211,14 @@ fn resolve_dynamic_call(
9581211 args : & [ ExprId ] ,
9591212 body : & Body ,
9601213) -> Option < CallDef > {
961- // Extract arity from the arguments list
962- let arity = arity_from_apply_args ( args[ pattern. args_list_index ] , body) ?;
1214+ // Extract arity based on pattern type
1215+ let arity = if pattern. direct_arity {
1216+ // Extract arity directly from an integer argument
1217+ arity_from_integer_arg ( args[ pattern. args_list_index ] , body) ?
1218+ } else {
1219+ // Extract arity from list length
1220+ arity_from_apply_args ( args[ pattern. args_list_index ] , body) ?
1221+ } ;
9631222
9641223 // Build the call target
9651224 let call_target = if let Some ( module_idx) = pattern. module_arg_index {
@@ -986,3 +1245,12 @@ fn arity_from_apply_args(args: ExprId, body: &Body) -> Option<u32> {
9861245 // Deal with a simple list only.
9871246 body[ args] . list_length ( ) . map ( |l| l as u32 )
9881247}
1248+
1249+ /// Extract arity directly from an integer argument.
1250+ /// Given the `ExprId` of an integer parameter, return its value as arity.
1251+ fn arity_from_integer_arg ( arity_arg : ExprId , body : & Body ) -> Option < u32 > {
1252+ match & body[ arity_arg] {
1253+ Expr :: Literal ( Literal :: Integer ( int) ) => int. value . try_into ( ) . ok ( ) ,
1254+ _ => None ,
1255+ }
1256+ }
0 commit comments