@@ -1031,23 +1031,26 @@ defmodule Module.Types.Descr do
10311031
10321032 # For non-dynamic function and arguments, just return the static result
10331033 if fun_dynamic == nil and not args_dynamic? do
1034- fun_apply_static ( fun_static , arguments , :static )
1034+ fun_apply_static ( fun_static , arguments , :static , args_dynamic? )
10351035 else
10361036 # For dynamic cases, combine static and dynamic results
1037- { static_args , dynamic_args } =
1038- if args_dynamic? ,
1039- do: { materialize_arguments ( arguments , :up ) , materialize_arguments ( arguments , :down ) } ,
1040- else: { arguments , arguments }
1037+ { static_args , dynamic_args , maybe_empty? } =
1038+ if args_dynamic? do
1039+ { materialize_arguments ( arguments , :up ) , materialize_arguments ( arguments , :down ) , true }
1040+ else
1041+ { arguments , arguments , false }
1042+ end
10411043
1042- case fun_apply_static ( fun_static , static_args , :static ) do
1044+ case fun_apply_static ( fun_static , static_args , :static , false ) do
10431045 { :ok , res1 } when fun_dynamic == nil ->
1044- with { :ok , res2 } <- fun_apply_static ( fun_static , dynamic_args , :static ) do
1046+ # We need to compute which parts are dynamic
1047+ with { :ok , res2 } <- fun_apply_static ( fun_static , dynamic_args , :static , maybe_empty? ) do
10451048 { :ok , union ( res1 , dynamic ( res2 ) ) }
10461049 end
10471050
10481051 { :ok , res1 } when fun_dynamic != nil ->
10491052 # If static succeeded, the dynamic part can fail, we don't care
1050- case fun_apply_static ( fun_dynamic , dynamic_args , :dynamic ) do
1053+ case fun_apply_static ( fun_dynamic , dynamic_args , :dynamic , maybe_empty? ) do
10511054 { :ok , res2 } -> { :ok , union ( res1 , dynamic ( res2 ) ) }
10521055 _ -> { :ok , res1 }
10531056 end
@@ -1056,9 +1059,9 @@ defmodule Module.Types.Descr do
10561059 # Then the dynamic call has to succeed
10571060 result =
10581061 if fun_dynamic do
1059- fun_apply_static ( fun_dynamic , dynamic_args , :dynamic )
1062+ fun_apply_static ( fun_dynamic , dynamic_args , :dynamic , maybe_empty? )
10601063 else
1061- fun_apply_static ( fun_static , dynamic_args , :static )
1064+ fun_apply_static ( fun_static , dynamic_args , :static , maybe_empty? )
10621065 end
10631066
10641067 with { :ok , descr } <- result do
@@ -1078,15 +1081,15 @@ defmodule Module.Types.Descr do
10781081
10791082 defp are_arguments_dynamic? ( arguments ) , do: Enum . any? ( arguments , & match? ( % { dynamic: _ } , & 1 ) )
10801083
1081- defp fun_apply_static ( % { fun: fun_bdd } , arguments , mode ) do
1084+ defp fun_apply_static ( % { fun: fun_bdd } , arguments , mode , maybe_empty? ) do
10821085 arity = length ( arguments )
10831086
10841087 with { :ok , domain , arrows } <- fun_normalize ( fun_bdd , arity , mode ) do
10851088 type_args = domain_descr ( arguments )
10861089
10871090 cond do
1088- empty? ( type_args ) ->
1089- # Opti: short-circuits when inner loop is none() or outer loop is term()
1091+ # Optization: short-circuits when inner loop is none() or outer loop is term()
1092+ maybe_empty? and empty? ( type_args ) ->
10901093 result =
10911094 Enum . reduce_while ( arrows , none ( ) , fn intersection_of_arrows , acc ->
10921095 Enum . reduce_while ( intersection_of_arrows , term ( ) , fn
@@ -1115,7 +1118,7 @@ defmodule Module.Types.Descr do
11151118 end
11161119 end
11171120
1118- defp fun_apply_static ( % { } , _arguments , _mode ) do
1121+ defp fun_apply_static ( % { } , _arguments , _mode , _maybe_empty? ) do
11191122 :badfun
11201123 end
11211124
0 commit comments