aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_ssa_type.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2019-02-22 11:29:57 +0100
committerBjörn Gustavsson <[email protected]>2019-02-22 11:29:57 +0100
commitd0ce82e6a1538de602afa558e71977884fa2e8aa (patch)
tree15a25458c7c7bf5f1cbc1f3504327da028451b79 /lib/compiler/src/beam_ssa_type.erl
parent3cec819e8eb3cd992242f58aae22d06feef070d6 (diff)
parent547476f4d47c90b3d02314f5f1f327cdacf5e587 (diff)
downloadotp-d0ce82e6a1538de602afa558e71977884fa2e8aa.tar.gz
otp-d0ce82e6a1538de602afa558e71977884fa2e8aa.tar.bz2
otp-d0ce82e6a1538de602afa558e71977884fa2e8aa.zip
Merge branch 'bjorn/compiler/use-lists-types'
* bjorn/compiler/use-lists-types: beam_ssa_type: Use types from some 'lists' functions
Diffstat (limited to 'lib/compiler/src/beam_ssa_type.erl')
-rw-r--r--lib/compiler/src/beam_ssa_type.erl67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index c040fb2dde..aa4720d222 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -884,6 +884,9 @@ type(call, [#b_remote{mod=#b_literal{val=Mod},
end;
{erlang,'--',[_,_]} ->
list;
+ {lists,F,Args} ->
+ Types = get_types(Args, Ts),
+ lists_function_type(F, Types);
{math,_,_} ->
case is_math_bif(Name, length(Args)) of
false -> any;
@@ -975,6 +978,70 @@ arith_op_type(Args, Ts) ->
(_, _) -> none
end, unknown, Types).
+lists_function_type(F, Types) ->
+ case {F,Types} of
+ %% Functions that return booleans.
+ {all,[_,_]} ->
+ t_boolean();
+ {any,[_,_]} ->
+ t_boolean();
+ {keymember,[_,_,_]} ->
+ t_boolean();
+ {member,[_,_]} ->
+ t_boolean();
+ {prefix,[_,_]} ->
+ t_boolean();
+ {suffix,[_,_]} ->
+ t_boolean();
+
+ %% Functions that return lists.
+ {dropwhile,[_,_]} ->
+ list;
+ {duplicate,[_,_]} ->
+ list;
+ {filter,[_,_]} ->
+ list;
+ {flatten,[_]} ->
+ list;
+ {map,[_Fun,List]} ->
+ same_length_type(List);
+ {MapFold,[_Fun,_Acc,List]} when MapFold =:= mapfoldl;
+ MapFold =:= mapfoldr ->
+ #t_tuple{size=2,exact=true,
+ elements=#{1=>same_length_type(List)}};
+ {partition,[_,_]} ->
+ t_two_tuple(list, list);
+ {reverse,[List]} ->
+ same_length_type(List);
+ {sort,[List]} ->
+ same_length_type(List);
+ {splitwith,[_,_]} ->
+ t_two_tuple(list, list);
+ {takewhile,[_,_]} ->
+ list;
+ {unzip,[List]} ->
+ ListType = same_length_type(List),
+ t_two_tuple(ListType, ListType);
+ {usort,[List]} ->
+ same_length_type(List);
+ {zip,[_,_]} ->
+ list;
+ {zipwith,[_,_,_]} ->
+ list;
+ {_,_} ->
+ any
+ end.
+
+%% For a lists function that return a list of the same
+%% length as the input list, return the type of the list.
+same_length_type(cons) -> cons;
+same_length_type(nil) -> nil;
+same_length_type(_) -> list.
+
+t_two_tuple(Type1, Type2) ->
+ #t_tuple{size=2,exact=true,
+ elements=#{1=>Type1,2=>Type2}}.
+
%% will_succeed(TestOperation, Type) -> yes|no|maybe.
%% Test whether TestOperation applied to an argument of type Type
%% will succeed. Return yes, no, or maybe.