aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2013-11-06 09:01:30 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-01-28 17:06:41 +0100
commit351987be44e11e6eb9e5841adb197ec8e49bc49d (patch)
treec4661b09df606fbe7d50921651d1ad707150e971 /lib/dialyzer
parent72146c6675aaff02b2452c2fd2026c111e641f35 (diff)
downloadotp-351987be44e11e6eb9e5841adb197ec8e49bc49d.tar.gz
otp-351987be44e11e6eb9e5841adb197ec8e49bc49d.tar.bz2
otp-351987be44e11e6eb9e5841adb197ec8e49bc49d.zip
dialyzer,hipe,stdlib: Add Maps understanding to Dialyzer
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl2
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl56
-rw-r--r--lib/dialyzer/src/dialyzer_dep.erl12
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl34
4 files changed, 100 insertions, 4 deletions
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index a7be6e0d05..cda801bf6c 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -603,7 +603,7 @@ cl_loop(State, LogCache) ->
Msg = failed_anal_msg(Reason, LogCache),
cl_error(State, Msg);
{'EXIT', BackendPid, Reason} when Reason =/= 'normal' ->
- Msg = failed_anal_msg(io_lib:format("~P", [Reason, 12]), LogCache),
+ Msg = failed_anal_msg(io_lib:format("~p", [Reason]), LogCache),
cl_error(State, Msg);
_Other ->
%% io:format("Received ~p\n", [_Other]),
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 3591d5be8e..4d614320c2 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -67,7 +67,9 @@
t_to_string/2, t_to_tlist/1,
t_tuple/0, t_tuple/1, t_tuple_args/1, t_tuple_args/2,
t_tuple_subtypes/2,
- t_unit/0, t_unopaque/2]).
+ t_unit/0, t_unopaque/2,
+ t_map/1
+ ]).
%%-define(DEBUG, true).
%%-define(DEBUG_PP, true).
@@ -305,6 +307,12 @@ traverse(Tree, Map, State) ->
handle_try(Tree, Map, State);
tuple ->
handle_tuple(Tree, Map, State);
+ map ->
+ handle_map(Tree, Map, State);
+ map_pair_assoc ->
+ handle_map_pair_assoc(Tree, Map, State);
+ map_pair_exact ->
+ handle_map_pair_exact(Tree, Map, State);
values ->
Elements = cerl:values_es(Tree),
{State1, Map1, EsType} = traverse_list(Elements, Map, State),
@@ -657,7 +665,8 @@ is_opaque_type_test_problem(Fun, Args, ArgTypes, State) ->
FN =:= is_float; FN =:= is_function;
FN =:= is_integer; FN =:= is_list;
FN =:= is_number; FN =:= is_pid; FN =:= is_port;
- FN =:= is_reference; FN =:= is_tuple ->
+ FN =:= is_reference; FN =:= is_tuple;
+ FN =:= is_map ->
type_test_opaque_arg(Args, ArgTypes, State#state.opaques);
{erlang, FN, 2} when FN =:= is_function ->
type_test_opaque_arg(Args, ArgTypes, State#state.opaques);
@@ -1054,6 +1063,23 @@ handle_try(Tree, Map, State) ->
%%----------------------------------------
+handle_map(Tree,Map,State) ->
+ Pairs = cerl:map_es(Tree),
+ {State1, Map1, TypePairs} = traverse_list(Pairs,Map,State),
+ {State1, Map1, t_map(TypePairs)}.
+
+handle_map_pair_assoc(Tree,Map,State) ->
+ Elements = cerl:map_pair_assoc_es(Tree),
+ {State1, Map1, [K,V]} = traverse_list(Elements,Map,State),
+ {State1, Map1, {K,V}}.
+
+handle_map_pair_exact(Tree,Map,State) ->
+ Elements = cerl:map_pair_exact_es(Tree),
+ {State1, Map1, [K,V]} = traverse_list(Elements,Map,State),
+ {State1, Map1, {K,V}}.
+
+%%----------------------------------------
+
handle_tuple(Tree, Map, State) ->
Elements = cerl:tuple_es(Tree),
{State1, Map1, EsType} = traverse_list(Elements, Map, State),
@@ -1431,6 +1457,30 @@ bind_pat_vars([Pat|PatLeft], [Type|TypeLeft], Acc, Map, State, Rev) ->
bind_opaque_pats(Literal, Type, Pat, Map, State, Rev);
false -> {Map, Literal}
end;
+ map ->
+ {Map, t_map([])};
+% Pairs = [ cerl:map_pair_es(Pair) || Pair <- cerl:map_es(Pat) ],
+% MapType = t_inf(t_map([]), Type),
+% case t_is_none(MapType) of
+% true ->
+% bind_opaque_pats(MapType, Type, Pat, Map, State, Rev);
+% false ->
+% MapJ = join_maps_begin(Map),
+% Results = case Rev of
+% true ->
+% [bind_pat_vars_reverse(Pair, [t_any(),t_any()], [], MapJ, State) || Pair <- Pairs];
+% false ->
+% [bind_pat_vars(Pair, [t_any(),t_any()], [], MapJ, State) || Pair <- Pairs]
+% end,
+% case [M || {M, _} <- Results, M =/= error] of
+% [] -> bind_error([Pat], MapType, t_none(), bind);
+% Maps ->
+% Map1 = join_maps_end(Maps, MapJ),
+% _PairTypes = [{Ktype,Vtype} || {M, [Ktype,Vtype]} <- Results, M =/= error],
+% % add t_sup
+% {Map1, t_map([])}
+% end
+% end;
tuple ->
Es = cerl:tuple_es(Pat),
{TypedRecord, Prototype} =
@@ -1641,6 +1691,8 @@ bind_guard(Guard, Map, Env, Eval, State) ->
Es0 = cerl:tuple_es(Guard),
{Map1, Es} = bind_guard_list(Es0, Map, Env, dont_know, State),
{Map1, t_tuple(Es)};
+ map ->
+ {Map, t_map([])};
'let' ->
Arg = cerl:let_arg(Guard),
[Var] = cerl:let_vars(Guard),
diff --git a/lib/dialyzer/src/dialyzer_dep.erl b/lib/dialyzer/src/dialyzer_dep.erl
index 05f81399fb..12833b49c7 100644
--- a/lib/dialyzer/src/dialyzer_dep.erl
+++ b/lib/dialyzer/src/dialyzer_dep.erl
@@ -182,6 +182,18 @@ traverse(Tree, Out, State, CurrentFun) ->
Args = cerl:tuple_es(Tree),
{List, State1} = traverse_list(Args, Out, State, CurrentFun),
{merge_outs(List), State1};
+ map ->
+ Args = cerl:map_es(Tree),
+ {List, State1} = traverse_list(Args, Out, State, CurrentFun),
+ {merge_outs(List), State1};
+ map_pair_assoc ->
+ Args = cerl:map_pair_assoc_es(Tree),
+ {List, State1} = traverse_list(Args, Out, State, CurrentFun),
+ {merge_outs(List), State1};
+ map_pair_exact ->
+ Args = cerl:map_pair_exact_es(Tree),
+ {List, State1} = traverse_list(Args, Out, State, CurrentFun),
+ {merge_outs(List), State1};
values ->
traverse_list(cerl:values_es(Tree), Out, State, CurrentFun);
var ->
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index db7875704a..4e18e9c7d2 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -55,7 +55,9 @@
t_subst/2,
t_timeout/0, t_tuple/0, t_tuple/1,
t_var/1, t_var_name/1,
- t_none/0, t_unit/0]).
+ t_none/0, t_unit/0,
+ t_map/1
+ ]).
-include("dialyzer.hrl").
@@ -470,6 +472,33 @@ traverse(Tree, DefinedVars, State) ->
end;
[] -> {State2, TupleType}
end;
+ map ->
+ {State, t_map([])};
+% Pairs = cerl:map_es(Tree),
+% {State1, EVars} = traverse_list(Pairs, DefinedVars, State),
+% case cerl:is_literal(cerl:fold_literal(Tree)) of
+% true ->
+% %% We do not need to do anything more here.
+% {State, t_map([])};
+% false ->
+% Fun = fun(Var, AccState) ->
+% case t_has_var(Var) of
+% true ->
+% {AccState1, NewVar} = state__mk_var(AccState),
+% {NewVar,
+% state__store_conj(Var, eq, NewVar, AccState1)};
+% false ->
+% {Var, AccState}
+% end
+% end,
+% {_NewEvars, State2} = lists:mapfoldl(Fun, State1, EVars),
+% {State2, t_map([])}
+% end;
+% map_pair_assoc ->
+% [K,V] = cerl:map_pair_assoc_es(Tree),
+% {State1,_} = traverse(K,DefinedVars,State),
+% {State2,_} = traverse(V,DefinedVars,State),
+% {_,State2};
values ->
%% We can get into trouble when unifying products that have the
%% same element appearing several times. Handle these cases by
@@ -1037,6 +1066,9 @@ get_safe_underapprox_1([Pat|Left], Acc, Map) ->
{Ts, Map1} = get_safe_underapprox_1(Es, [], Map),
Type = t_tuple(Ts),
get_safe_underapprox_1(Left, [Type|Acc], Map1);
+ map ->
+ %% TODO: Can maybe do something here
+ throw(dont_know);
values ->
Es = cerl:values_es(Pat),
{Ts, Map1} = get_safe_underapprox_1(Es, [], Map),