aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src
diff options
context:
space:
mode:
authorHans Bolinder <[email protected]>2017-03-15 11:34:36 +0100
committerHans Bolinder <[email protected]>2017-06-13 13:40:25 +0200
commit020a8817caca2684f8241dc5f9c84a37d53b4ff7 (patch)
treed2a9e1e455a292777d9d90b17e21a1d5ec186e33 /lib/dialyzer/src
parentf05dd185fe56cccdefeca8bd3fa92ec6c0e7979d (diff)
downloadotp-020a8817caca2684f8241dc5f9c84a37d53b4ff7.tar.gz
otp-020a8817caca2684f8241dc5f9c84a37d53b4ff7.tar.bz2
otp-020a8817caca2684f8241dc5f9c84a37d53b4ff7.zip
dialyzer: Minor optimizations
Avoid some ETS-lookups. Marginal speed-ups.
Diffstat (limited to 'lib/dialyzer/src')
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl58
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl6
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl7
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl130
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl10
5 files changed, 112 insertions, 99 deletions
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index 300af7956d..b554ebc2cc 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -18,7 +18,7 @@
check_contracts/4,
contracts_without_fun/3,
contract_to_string/1,
- get_invalid_contract_warnings/4,
+ get_invalid_contract_warnings/3,
get_contract_args/1,
get_contract_return/1,
get_contract_return/2,
@@ -173,22 +173,20 @@ process_contract_remote_types(CodeServer) ->
lists:foreach(ModuleFun, Mods),
dialyzer_codeserver:finalize_contracts(CodeServer).
--type opaques_fun() :: fun((module()) -> [erl_types:erl_type()]).
+-type fun_types() :: orddict:orddict(label(), erl_types:type_table()).
--type fun_types() :: dict:dict(label(), erl_types:type_table()).
-
--spec check_contracts(orddict:orddict(mfa(), file_contract()),
+-spec check_contracts(orddict:orddict(mfa(), #contract{}),
dialyzer_callgraph:callgraph(), fun_types(),
- opaques_fun()) -> plt_contracts().
+ erl_types:opaques()) -> plt_contracts().
-check_contracts(Contracts, Callgraph, FunTypes, FindOpaques) ->
+check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) ->
FoldFun =
- fun(Label, Type, NewContracts) ->
+ fun({Label, Type}, NewContracts) ->
case dialyzer_callgraph:lookup_name(Label, Callgraph) of
{ok, {M,F,A} = MFA} ->
case orddict:find(MFA, Contracts) of
- {ok, {_FileLine, Contract, _Xtra}} ->
- Opaques = FindOpaques(M),
+ {ok, Contract} ->
+ {M, Opaques} = lists:keyfind(M, 1, ModOpaques),
case check_contract(Contract, Type, Opaques) of
ok ->
case erl_bif_types:is_known(M, F, A) of
@@ -206,7 +204,7 @@ check_contracts(Contracts, Callgraph, FunTypes, FindOpaques) ->
error -> NewContracts
end
end,
- orddict:from_list(dict:fold(FoldFun, [], FunTypes)).
+ orddict:from_list(lists:foldl(FoldFun, [], orddict:to_list(FunTypes))).
%% Checks all components of a contract
-spec check_contract(#contract{}, erl_types:erl_type()) -> 'ok' | {'error', term()}.
@@ -214,6 +212,9 @@ check_contracts(Contracts, Callgraph, FunTypes, FindOpaques) ->
check_contract(Contract, SuccType) ->
check_contract(Contract, SuccType, 'universe').
+-spec check_contract(#contract{}, erl_types:erl_type(), erl_types:opaques()) ->
+ 'ok' | {'error', term()}.
+
check_contract(#contract{contracts = Contracts}, SuccType, Opaques) ->
try
Contracts1 = [{Contract, insert_constraints(Constraints)}
@@ -662,32 +663,37 @@ general_domain([], AccSig) ->
-spec get_invalid_contract_warnings([module()],
dialyzer_codeserver:codeserver(),
- dialyzer_plt:plt(),
- opaques_fun()) -> [raw_warning()].
+ dialyzer_plt:plt()) -> [raw_warning()].
-get_invalid_contract_warnings(Modules, CodeServer, Plt, FindOpaques) ->
- get_invalid_contract_warnings_modules(Modules, CodeServer, Plt, FindOpaques, []).
+get_invalid_contract_warnings(Modules, CodeServer, Plt) ->
+ get_invalid_contract_warnings_modules(Modules, CodeServer, Plt, []).
-get_invalid_contract_warnings_modules([Mod|Mods], CodeServer, Plt, FindOpaques, Acc) ->
+get_invalid_contract_warnings_modules([Mod|Mods], CodeServer, Plt, Acc) ->
Contracts1 = dialyzer_codeserver:lookup_mod_contracts(Mod, CodeServer),
- Contracts2 = maps:to_list(Contracts1),
- Records = dialyzer_codeserver:lookup_mod_records(Mod, CodeServer),
- NewAcc = get_invalid_contract_warnings_funs(Contracts2, Plt, Records, FindOpaques, Acc),
- get_invalid_contract_warnings_modules(Mods, CodeServer, Plt, FindOpaques, NewAcc);
-get_invalid_contract_warnings_modules([], _CodeServer, _Plt, _FindOpaques, Acc) ->
+ NewAcc =
+ case maps:size(Contracts1) =:= 0 of
+ true -> Acc;
+ false ->
+ Contracts2 = maps:to_list(Contracts1),
+ Records = dialyzer_codeserver:lookup_mod_records(Mod, CodeServer),
+ Opaques = erl_types:t_opaque_from_records(Records),
+ get_invalid_contract_warnings_funs(Contracts2, Plt, Records,
+ Opaques, Acc)
+ end,
+ get_invalid_contract_warnings_modules(Mods, CodeServer, Plt, NewAcc);
+get_invalid_contract_warnings_modules([], _CodeServer, _Plt, Acc) ->
Acc.
get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left],
- Plt, RecDict, FindOpaques, Acc) ->
+ Plt, RecDict, Opaques, Acc) ->
case dialyzer_plt:lookup(Plt, MFA) of
none ->
%% This must be a contract for a non-available function. Just accept it.
- get_invalid_contract_warnings_funs(Left, Plt, RecDict, FindOpaques, Acc);
+ get_invalid_contract_warnings_funs(Left, Plt, RecDict, Opaques, Acc);
{value, {Ret, Args}} ->
Sig = erl_types:t_fun(Args, Ret),
{M, _F, _A} = MFA,
%% io:format("MFA ~tp~n", [MFA]),
- Opaques = FindOpaques(M),
{File, Line} = FileLine,
WarningInfo = {File, Line, MFA},
NewAcc =
@@ -741,9 +747,9 @@ get_invalid_contract_warnings_funs([{MFA, {FileLine, Contract, _Xtra}}|Left],
RecDict, Acc)
end
end,
- get_invalid_contract_warnings_funs(Left, Plt, RecDict, FindOpaques, NewAcc)
+ get_invalid_contract_warnings_funs(Left, Plt, RecDict, Opaques, NewAcc)
end;
-get_invalid_contract_warnings_funs([], _Plt, _RecDict, _FindOpaques, Acc) ->
+get_invalid_contract_warnings_funs([], _Plt, _RecDict, _Opaques, Acc) ->
Acc.
invalid_contract_warning({M, F, A}, WarningInfo, SuccType, RecDict) ->
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 46a8f01360..8367432ac5 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -138,7 +138,7 @@
%%--------------------------------------------------------------------
--type fun_types() :: dict:dict(label(), type()).
+-type fun_types() :: orddict:orddict(label(), type()).
-spec get_warnings(cerl:c_module(), dialyzer_plt:plt(),
dialyzer_callgraph:callgraph(),
@@ -3317,7 +3317,9 @@ state__clean_not_called(#state{fun_tab = FunTab} = State) ->
state__all_fun_types(State) ->
#state{fun_tab = FunTab} = state__clean_not_called(State),
Tab1 = dict:erase(top, FunTab),
- dict:map(fun(_Fun, {Args, Ret}) -> t_fun(Args, Ret)end, Tab1).
+ List = [{Fun, t_fun(Args, Ret)} ||
+ {Fun, {Args, Ret}} <- dict:to_list(Tab1)],
+ orddict:from_list(List).
state__fun_type(Fun, #state{fun_tab = FunTab}) ->
Label =
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index f36a008739..fa242555c2 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -39,6 +39,7 @@
insert_types/2,
insert_exported_types/2,
lookup/2,
+ is_contract/2,
lookup_contract/2,
lookup_callbacks/2,
lookup_module/2,
@@ -156,6 +157,12 @@ insert_callbacks(#plt{callbacks = Callbacks} = Plt, Codeserver) ->
List = dialyzer_codeserver:get_callbacks(Codeserver),
Plt#plt{callbacks = table_insert_list(Callbacks, List)}.
+-spec is_contract(plt(), mfa()) -> boolean().
+
+is_contract(#mini_plt{contracts = ETSContracts},
+ {M, F, _} = MFA) when is_atom(M), is_atom(F) ->
+ ets:member(ETSContracts, MFA).
+
-spec lookup_contract(plt(), mfa_patt()) -> 'none' | {'value', #contract{}}.
lookup_contract(#mini_plt{contracts = ETSContracts},
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 93f7d4519b..c221915a1b 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -140,10 +140,9 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver,
TimingServer, Solvers, Parent),
Mods = dialyzer_callgraph:modules(InitState#st.callgraph),
MiniPlt = InitState#st.plt,
- FindOpaques = lookup_and_find_opaques_fun(Codeserver),
CWarns =
dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver,
- MiniPlt, FindOpaques),
+ MiniPlt),
MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt),
ModWarns =
?timing(TimingServer, "warning",
@@ -255,20 +254,18 @@ refine_one_module(M, {CodeServer, Callgraph, Plt, _Solvers}) ->
Records = dialyzer_codeserver:lookup_mod_records(M, CodeServer),
NewFunTypes =
dialyzer_dataflow:get_fun_types(ModCode, Plt, Callgraph, CodeServer, Records),
- Contracts1 = dialyzer_codeserver:lookup_mod_contracts(M, CodeServer),
- Contracts = orddict:from_list(maps:to_list(Contracts1)),
- FindOpaques = find_opaques_fun(Records),
- DecoratedFunTypes =
- decorate_succ_typings(Contracts, Callgraph, NewFunTypes, FindOpaques),
- %% ?debug("NewFunTypes ~tp\n ~n", [dict:to_list(NewFunTypes)]),
- %% ?debug("refine DecoratedFunTypes ~tp\n ~n", [dict:to_list(DecoratedFunTypes)]),
+ {FunMFAContracts, ModOpaques} =
+ prepare_decoration(NewFunTypes, Callgraph, CodeServer),
+ DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
+ %% ?Debug("NewFunTypes ~tp\n ~n", [NewFunTypes]),
+ %% ?debug("refine DecoratedFunTypes ~tp\n ~n", [DecoratedFunTypes]),
debug_pp_functions("Refine", NewFunTypes, DecoratedFunTypes, Callgraph),
case reached_fixpoint(FunTypes, DecoratedFunTypes) of
true -> [];
{false, NotFixpoint} ->
?debug("Not fixpoint\n", []),
- Plt = insert_into_plt(dict:from_list(NotFixpoint), Callgraph, Plt),
+ Plt = insert_into_plt(orddict:from_list(NotFixpoint), Callgraph, Plt),
[FunLbl || {FunLbl,_Type} <- NotFixpoint]
end.
@@ -282,22 +279,20 @@ reached_fixpoint_strict(OldTypes, NewTypes) ->
end.
reached_fixpoint(OldTypes0, NewTypes0, Strict) ->
- MapFun = fun(_Key, Type) ->
+ MapFun = fun({Key, Type}) ->
case is_failed_or_not_called_fun(Type) of
- true -> failed_fun;
- false -> erl_types:t_limit(Type, ?TYPE_LIMIT)
+ true -> {Key, failed_fun};
+ false -> {Key, erl_types:t_limit(Type, ?TYPE_LIMIT)}
end
end,
- OldTypes = dict:map(MapFun, OldTypes0),
- NewTypes = dict:map(MapFun, NewTypes0),
+ OldTypes = lists:map(MapFun, orddict:to_list(OldTypes0)),
+ NewTypes = lists:map(MapFun, orddict:to_list(NewTypes0)),
compare_types(OldTypes, NewTypes, Strict).
is_failed_or_not_called_fun(Type) ->
erl_types:any_none([erl_types:t_fun_range(Type)|erl_types:t_fun_args(Type)]).
-compare_types(Dict1, Dict2, Strict) ->
- List1 = lists:keysort(1, dict:to_list(Dict1)),
- List2 = lists:keysort(1, dict:to_list(Dict2)),
+compare_types(List1, List2, Strict) ->
compare_types_1(List1, List2, Strict, []).
compare_types_1([{X, _Type1}|Left1], [{X, failed_fun}|Left2],
@@ -344,10 +339,6 @@ find_succ_typings(SCCs, #st{codeserver = Codeserver, callgraph = Callgraph,
find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
SCC = [MFA || {_, _, _} = MFA <- SCC0],
- Contracts1 = [{MFA, dialyzer_codeserver:lookup_mfa_contract(MFA, Codeserver)}
- || MFA <- SCC],
- Contracts2 = [{MFA, Contract} || {MFA, {ok, Contract}} <- Contracts1],
- Contracts3 = orddict:from_list(Contracts2),
Label = dialyzer_codeserver:get_next_core_label(Codeserver),
AllFuns = lists:append(
[begin
@@ -355,7 +346,6 @@ find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver),
collect_fun_info([Fun])
end || MFA <- SCC]),
- erlang:garbage_collect(),
PropTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt),
%% Assume that the PLT contains the current propagated types
FunTypes = dialyzer_typesig:analyze_scc(SCC, Label, Callgraph,
@@ -363,27 +353,28 @@ find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
Solvers),
AllFunSet = sets:from_list([X || {X, _} <- AllFuns]),
FilteredFunTypes =
- dict:filter(fun(X, _) -> sets:is_element(X, AllFunSet) end, FunTypes),
- FindOpaques = lookup_and_find_opaques_fun(Codeserver),
- DecoratedFunTypes =
- decorate_succ_typings(Contracts3, Callgraph, FilteredFunTypes, FindOpaques),
+ orddict:filter(fun(F, _T) -> sets:is_element(F, AllFunSet)
+ end, FunTypes),
+ {FunMFAContracts, ModOpaques} =
+ prepare_decoration(FilteredFunTypes, Callgraph, Codeserver),
+ DecoratedFunTypes = decorate_succ_typings(FunMFAContracts, ModOpaques),
%% Check contracts
+ Contracts = orddict:from_list([{MFA, Contract} ||
+ {_, {MFA, Contract}} <- FunMFAContracts]),
PltContracts =
- dialyzer_contracts:check_contracts(Contracts3, Callgraph,
- DecoratedFunTypes, FindOpaques),
- %% ?debug("FilteredFunTypes ~tp\n ~n", [dict:to_list(FilteredFunTypes)]),
- %% ?debug("SCC DecoratedFunTypes ~tp\n ~n", [dict:to_list(DecoratedFunTypes)]),
+ dialyzer_contracts:check_contracts(Contracts, Callgraph,
+ DecoratedFunTypes,
+ ModOpaques),
+ %% ?debug("FilteredFunTypes ~tp\n ~n", [FilteredFunTypes]),
+ %% ?debug("SCC DecoratedFunTypes ~tp\n ~n", [DecoratedFunTypes]),
debug_pp_functions("SCC", FilteredFunTypes, DecoratedFunTypes, Callgraph),
- ContractFixpoint =
- lists:all(fun({MFA, _C}) ->
- %% Check the non-deleted PLT
- case dialyzer_plt:lookup_contract(Plt, MFA) of
- none -> false;
- {value, _} -> true
- end
- end, PltContracts),
+ NewPltContracts = [MC ||
+ {MFA, _C}=MC <- PltContracts,
+ %% Check the non-deleted PLT
+ not dialyzer_plt:is_contract(Plt, MFA)],
+ ContractFixpoint = NewPltContracts =:= [],
Plt = insert_into_plt(DecoratedFunTypes, Callgraph, Plt),
- Plt = dialyzer_plt:insert_contract_list(Plt, PltContracts),
+ Plt = dialyzer_plt:insert_contract_list(Plt, NewPltContracts),
case (ContractFixpoint andalso
reached_fixpoint_strict(PropTypes, DecoratedFunTypes)) of
true -> [];
@@ -392,42 +383,49 @@ find_succ_types_for_scc(SCC0, {Codeserver, Callgraph, Plt, Solvers}) ->
[Fun || {Fun, _Arity} <- AllFuns]
end.
-decorate_succ_typings(Contracts, Callgraph, FunTypes, FindOpaques) ->
- F = fun(Label, Type) ->
+prepare_decoration(FunTypes, Callgraph, Codeserver) ->
+ F = fun({Label, _Type}=LabelType, Acc) ->
case dialyzer_callgraph:lookup_name(Label, Callgraph) of
{ok, MFA} ->
- case orddict:find(MFA, Contracts) of
+ case dialyzer_codeserver:lookup_mfa_contract(MFA, Codeserver) of
{ok, {_FileLine, Contract, _Xtra}} ->
- Args = dialyzer_contracts:get_contract_args(Contract),
- Ret = dialyzer_contracts:get_contract_return(Contract),
- C = erl_types:t_fun(Args, Ret),
- {M, _, _} = MFA,
- Opaques = FindOpaques(M),
- erl_types:t_decorate_with_opaque(Type, C, Opaques);
- error -> Type
+ [{LabelType, {MFA, Contract}}|Acc];
+ error -> [{LabelType, no}|Acc]
end;
- error -> Type
+ error -> [{LabelType, no}|Acc]
end
end,
- dict:map(F, FunTypes).
-
-lookup_and_find_opaques_fun(Codeserver) ->
- fun(Module) ->
- Records = dialyzer_codeserver:lookup_mod_records(Module, Codeserver),
- (find_opaques_fun(Records))(Module)
- end.
+ Contracts = lists:foldl(F, [], orddict:to_list(FunTypes)),
+ ModOpaques =
+ [{M, lookup_opaques(M, Codeserver)} ||
+ M <- lists:usort([M || {_LabelType, {{M, _, _}, _Con}} <- Contracts])],
+ {Contracts, orddict:from_list(ModOpaques)}.
+
+decorate_succ_typings(FunTypesContracts, ModOpaques) ->
+ F = fun({{Label, Type}, {{M, _, _}, Contract}}) ->
+ Args = dialyzer_contracts:get_contract_args(Contract),
+ Ret = dialyzer_contracts:get_contract_return(Contract),
+ C = erl_types:t_fun(Args, Ret),
+ {M, Opaques} = lists:keyfind(M, 1, ModOpaques),
+ R = erl_types:t_decorate_with_opaque(Type, C, Opaques),
+ {Label, R};
+ ({LabelType, no}) ->
+ LabelType
+ end,
+ orddict:from_list(lists:map(F, FunTypesContracts)).
-find_opaques_fun(Records) ->
- fun(_Module) -> erl_types:t_opaque_from_records(Records) end.
+lookup_opaques(Module, Codeserver) ->
+ Records = dialyzer_codeserver:lookup_mod_records(Module, Codeserver),
+ erl_types:t_opaque_from_records(Records).
get_fun_types_from_plt(FunList, Callgraph, Plt) ->
- get_fun_types_from_plt(FunList, Callgraph, Plt, dict:new()).
+ get_fun_types_from_plt(FunList, Callgraph, Plt, []).
get_fun_types_from_plt([{FunLabel, Arity}|Left], Callgraph, Plt, Map) ->
Type = lookup_fun_type(FunLabel, Arity, Callgraph, Plt),
- get_fun_types_from_plt(Left, Callgraph, Plt, dict:store(FunLabel, Type, Map));
+ get_fun_types_from_plt(Left, Callgraph, Plt, [{FunLabel, Type}|Map]);
get_fun_types_from_plt([], _Callgraph, _Plt, Map) ->
- Map.
+ orddict:from_list(Map).
collect_fun_info(Trees) ->
collect_fun_info(Trees, []).
@@ -463,7 +461,7 @@ insert_into_plt(SuccTypes0, Callgraph, Plt) ->
dialyzer_plt:insert_list(Plt, SuccTypes).
format_succ_types(SuccTypes, Callgraph) ->
- format_succ_types(dict:to_list(SuccTypes), Callgraph, []).
+ format_succ_types(SuccTypes, Callgraph, []).
format_succ_types([{Label, Type0}|Left], Callgraph, Acc) ->
Type = erl_types:t_limit(Type0, ?TYPE_LIMIT+1),
@@ -486,10 +484,8 @@ debug_pp_succ_typings(SuccTypes) ->
?debug("\n", []),
ok.
-debug_pp_functions(Header, FunTypes, DecoratedFunTypes, Callgraph) ->
+debug_pp_functions(Header, FTypes, DTypes, Callgraph) ->
?debug("FunTypes (~s)\n", [Header]),
- FTypes = lists:keysort(1, dict:to_list(FunTypes)),
- DTypes = lists:keysort(1, dict:to_list(DecoratedFunTypes)),
Fun = fun({{Label, Type},{Label, DecoratedType}}) ->
Name = lookup_name(Label, Callgraph),
?debug("~tw (~w): ~ts\n",
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 80d55f9973..c4d8f45447 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -96,7 +96,8 @@
-type typesig_funmap() :: #{type_var() => type_var()}.
--type prop_types() :: dict:dict(label(), erl_types:erl_type()).
+-type prop_types() :: orddict:orddict(label(), erl_types:erl_type()).
+-type dict_prop_types() :: dict:dict(label(), erl_types:erl_type()).
-record(state, {callgraph :: dialyzer_callgraph:callgraph()
| 'undefined',
@@ -113,7 +114,7 @@
self_rec :: 'false' | erl_types:erl_type(),
plt :: dialyzer_plt:plt()
| 'undefined',
- prop_types = dict:new() :: prop_types(),
+ prop_types = dict:new() :: dict_prop_types(),
mod_records = [] :: [{module(), types()}],
scc = [] :: ordsets:ordset(type_var()),
mfas :: [mfa()],
@@ -186,7 +187,7 @@ analyze_scc(SCC, NextLabel, CallGraph, CServer, Plt, PropTypes, Solvers0) ->
pp_constrs_scc(Funs, State3),
constraints_to_dot_scc(Funs, State3),
T = solve(Funs, State3),
- dict:from_list(maps:to_list(T)).
+ orddict:from_list(maps:to_list(T)).
solvers([]) -> [v2];
solvers(Solvers) -> Solvers.
@@ -2706,7 +2707,7 @@ is_equal(Type1, Type2) ->
%%
%% ============================================================================
-new_state(MFAs, NextLabel, CallGraph, CServer, Plt, PropTypes, Solvers) ->
+new_state(MFAs, NextLabel, CallGraph, CServer, Plt, PropTypes0, Solvers) ->
List_SCC =
[begin
{Var, Label} = dialyzer_codeserver:lookup_mfa_var_label(MFA, CServer),
@@ -2724,6 +2725,7 @@ new_state(MFAs, NextLabel, CallGraph, CServer, Plt, PropTypes, Solvers) ->
end;
_Many -> false
end,
+ PropTypes = dict:from_list(PropTypes0),
#state{callgraph = CallGraph, name_map = NameMap, next_label = NextLabel,
prop_types = PropTypes, plt = Plt, scc = ordsets:from_list(SCC),
mfas = MFAs, self_rec = SelfRec, solvers = Solvers,