aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/doc/src/dialyzer.xml9
-rw-r--r--lib/dialyzer/src/dialyzer_behaviours.erl35
-rw-r--r--lib/dialyzer/src/dialyzer_callgraph.erl5
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl25
-rw-r--r--lib/dialyzer/src/dialyzer_codeserver.erl7
-rw-r--r--lib/dialyzer/src/dialyzer_typesig.erl16
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl9
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes16
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/types_arity2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/types_arity.erl20
10 files changed, 76 insertions, 68 deletions
diff --git a/lib/dialyzer/doc/src/dialyzer.xml b/lib/dialyzer/doc/src/dialyzer.xml
index 5e0c9b51e3..0ac96e8ac9 100644
--- a/lib/dialyzer/doc/src/dialyzer.xml
+++ b/lib/dialyzer/doc/src/dialyzer.xml
@@ -158,6 +158,9 @@
<item>Make Dialyzer a bit more quiet.</item>
<tag><c><![CDATA[--verbose]]></c></tag>
<item>Make Dialyzer a bit more verbose.</item>
+ <tag><c><![CDATA[--statistics]]></c></tag>
+ <item>Prints information about the progress of execution (analysis phases,
+ time spent in each and size of the relative input).</item>
<tag><c><![CDATA[--build_plt]]></c></tag>
<item>The analysis starts from an empty plt and creates a new one from
the files specified with <c><![CDATA[-c]]></c> and
@@ -228,6 +231,9 @@
match.</item>
<tag><c><![CDATA[-Wno_opaque]]></c></tag>
<item>Suppress warnings for violations of opaqueness of data types.</item>
+ <tag><c><![CDATA[-Wno_behaviours]]></c>***</tag>
+ <item>Suppress warnings about behaviour callbacks which drift from the
+ published recommended interfaces.</item>
<tag><c><![CDATA[-Wunmatched_returns]]></c>***</tag>
<item>Include warnings for function calls which ignore a structured return
value or do not match against one of many possible return
@@ -237,9 +243,6 @@
exception.</item>
<tag><c><![CDATA[-Wrace_conditions]]></c>***</tag>
<item>Include warnings for possible race conditions.</item>
- <tag><c><![CDATA[-Wbehaviours]]></c>***</tag>
- <item>Include warnings about behaviour callbacks which drift from the
- published recommended interfaces.</item>
<tag><c><![CDATA[-Wunderspecs]]></c>***</tag>
<item>Warn about underspecified functions
(the -spec is strictly more allowing than the success typing).</item>
diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl
index 36aef2a37f..bf0d08cf8f 100644
--- a/lib/dialyzer/src/dialyzer_behaviours.erl
+++ b/lib/dialyzer/src/dialyzer_behaviours.erl
@@ -25,8 +25,6 @@
%%%
%%% Created : 28 Oct 2009 by Stavros Aronis <[email protected]>
%%%-------------------------------------------------------------------
-%%% NOTE: This module is currently experimental -- do NOT rely on it!
-%%%-------------------------------------------------------------------
-module(dialyzer_behaviours).
@@ -127,15 +125,12 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest],
erl_types:t_to_string(CbReturnType, Records)]}|Acc00]
end
end,
- Acc02 =
- case erl_types:any_none(
- erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of
- false -> Acc01;
- true ->
- find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour,
- Function, Arity, Records, 1, Acc01)
- end,
- Acc02
+ case erl_types:any_none(erl_types:t_inf_lists(ArgTypes, CbArgTypes)) of
+ false -> Acc01;
+ true ->
+ find_mismatching_args(type, ArgTypes, CbArgTypes, Behaviour,
+ Function, Arity, Records, 1, Acc01)
+ end
end,
Acc2 =
case dialyzer_codeserver:lookup_mfa_contract(CbMFA, Codeserver) of
@@ -157,16 +152,14 @@ check_all_callbacks(Module, Behaviour, [Cb|Rest],
erl_types:t_to_string(ExtraType, Records),
erl_types:t_to_string(CbReturnType, Records)]}|Acc10]
end,
- Acc12 =
- case erl_types:any_none(
- erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of
- false -> Acc11;
- true ->
- find_mismatching_args({spec, File, Line}, SpecArgTypes,
- CbArgTypes, Behaviour, Function,
- Arity, Records, 1, Acc11)
- end,
- Acc12
+ case erl_types:any_none(
+ erl_types:t_inf_lists(SpecArgTypes, CbArgTypes)) of
+ false -> Acc11;
+ true ->
+ find_mismatching_args({spec, File, Line}, SpecArgTypes,
+ CbArgTypes, Behaviour, Function,
+ Arity, Records, 1, Acc11)
+ end
end,
NewAcc = Acc2,
check_all_callbacks(Module, Behaviour, Rest, State, NewAcc).
diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl
index 64e0ee88af..9e9226fa5a 100644
--- a/lib/dialyzer/src/dialyzer_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_callgraph.erl
@@ -798,10 +798,7 @@ condensation(G) ->
fun({V1, V2}) ->
I1 = ets:lookup_element(V2I, V1, 2),
I2 = ets:lookup_element(V2I, V2, 2),
- case I1 =:= I2 of
- true -> true;
- false -> ets:insert(I2I, {I1, I2})
- end
+ I1 =:= I2 orelse ets:insert(I2I, {I1, I2})
end,
lists:foreach(Fun1, digraph:edges(G)),
Fun3 =
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 6732d96b98..967aa989fb 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -488,6 +488,7 @@ expand_dependent_modules_1([Mod|Mods], Included, ModDeps) ->
expand_dependent_modules_1([], Included, _ModDeps) ->
Included.
+-define(MIN_PARALLELISM, 7).
-define(MIN_FILES_FOR_NATIVE_COMPILE, 20).
-spec hipe_compile([file:filename()], #options{}) -> 'ok'.
@@ -501,11 +502,14 @@ hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) ->
case erlang:system_info(hipe_architecture) of
undefined -> ok;
_ ->
- Mods = [lists, dict, gb_sets, gb_trees, ordsets, sets,
+ Mods = [lists, dict, digraph, digraph_utils, ets,
+ gb_sets, gb_trees, ordsets, sets, sofs,
cerl, cerl_trees, erl_types, erl_bif_types,
- dialyzer_analysis_callgraph, dialyzer_codeserver,
- dialyzer_dataflow, dialyzer_dep, dialyzer_plt,
- dialyzer_succ_typings, dialyzer_typesig],
+ dialyzer_analysis_callgraph, dialyzer, dialyzer_behaviours,
+ dialyzer_codeserver, dialyzer_contracts,
+ dialyzer_coordinator, dialyzer_dataflow, dialyzer_dep,
+ dialyzer_plt, dialyzer_succ_typings, dialyzer_typesig,
+ dialyzer_typesig, dialyzer_worker],
report_native_comp(Options),
{T1, _} = statistics(wall_clock),
native_compile(Mods),
@@ -515,12 +519,12 @@ hipe_compile(Files, #options{erlang_mode = ErlangMode} = Options) ->
end.
native_compile(Mods) ->
- case erlang:system_info(schedulers) of
- %% N when N > 1 ->
- %% Parent = self(),
- %% Pids = [spawn(fun () -> Parent ! {self(), hc(M)} end) || M <- Mods],
- %% lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids);
- _ -> % 1 ->
+ case dialyzer_utils:parallelism() > ?MIN_PARALLELISM of
+ true ->
+ Parent = self(),
+ Pids = [spawn(fun () -> Parent ! {self(), hc(M)} end) || M <- Mods],
+ lists:foreach(fun (Pid) -> receive {Pid, Res} -> Res end end, Pids);
+ false ->
lists:foreach(fun (Mod) -> hc(Mod) end, Mods)
end.
@@ -529,6 +533,7 @@ hc(Mod) ->
case code:is_module_native(Mod) of
true -> ok;
false ->
+ %% io:format(" ~s", [Mod]),
{ok, Mod} = hipe:c(Mod),
ok
end.
diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl
index 9989118671..5109bf968a 100644
--- a/lib/dialyzer/src/dialyzer_codeserver.erl
+++ b/lib/dialyzer/src/dialyzer_codeserver.erl
@@ -100,10 +100,7 @@ ets_dict_to_dict(Table) ->
ets:foldl(Fold, dict:new(), Table).
ets_set_is_element(Key, Table) ->
- case ets:lookup(Table, Key) of
- [] -> false;
- _ -> true
- end.
+ ets:lookup(Table, Key) =/= [].
ets_set_insert_set(Set, Table) ->
ets_set_insert_list(sets:to_list(Set), Table).
@@ -116,7 +113,7 @@ ets_set_to_set(Table) ->
ets:foldl(Fold, sets:new(), Table).
ets_read_concurrent_table(Name) ->
- ets:new(Name,[{read_concurrency, true}]).
+ ets:new(Name, [{read_concurrency, true}]).
%%--------------------------------------------------------------------
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 0df003a035..40d8936afa 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -1543,12 +1543,11 @@ get_bif_constr({erlang, '==', 2}, Dst, [Arg1, Arg2] = Args, _State) ->
mk_constraint(Arg1, sub, ArgV1),
mk_constraint(Arg2, sub, ArgV2)]);
get_bif_constr({erlang, element, 2} = _BIF, Dst, Args,
- #state{cs = Constrs} = State) ->
+ #state{cs = Constrs, opaques = Opaques}) ->
GenType = erl_bif_types:type(erlang, element, 2),
case t_is_none(GenType) of
true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error);
false ->
- Opaques = State#state.opaques,
Fun = fun(Map) ->
[I, T] = ATs = lookup_type_list(Args, Map),
ATs2 = case lists:member(T, Opaques) of
@@ -2582,19 +2581,8 @@ enter_type(Key, Val, Map) when is_integer(Key) ->
end
end;
enter_type(Key, Val, Map) ->
- ?debug("Entering ~s :: ~s\n", [format_type(Key), format_type(Val)]),
KeyName = t_var_name(Key),
- case t_is_any(Val) of
- true ->
- erase_type(KeyName, Map);
- false ->
- LimitedVal = t_limit(Val, ?INTERNAL_TYPE_LIMIT),
- case dict:find(KeyName, Map) of
- {ok, LimitedVal} -> Map;
- {ok, _} -> map_store(KeyName, LimitedVal, Map);
- error -> map_store(KeyName, LimitedVal, Map)
- end
- end.
+ enter_type(KeyName, Val, Map).
enter_type_lists([Key|KeyTail], [Val|ValTail], Map) ->
Map1 = enter_type(Key, Val, Map),
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 8046b48838..dc8e825199 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -219,15 +219,18 @@ get_record_and_type_info([], _Module, Records, RecDict) ->
end.
add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, RecDict) ->
- case erl_types:type_is_defined(TypeOrOpaque, Name, RecDict) of
+ Arity = length(ArgForms),
+ case erl_types:type_is_defined(TypeOrOpaque, Name, Arity, RecDict) of
true ->
- throw({error, flat_format("Type ~s already defined\n", [Name])});
+ Msg = flat_format("Type ~s/~w already defined\n", [Name, Arity]),
+ throw({error, Msg});
false ->
ArgTypes = [erl_types:t_from_form(X) || X <- ArgForms],
case lists:all(fun erl_types:t_is_var/1, ArgTypes) of
true ->
ArgNames = [erl_types:t_var_name(X) || X <- ArgTypes],
- dict:store({TypeOrOpaque, Name}, {Module, TypeForm, ArgNames}, RecDict);
+ dict:store({TypeOrOpaque, Name, Arity},
+ {Module, TypeForm, ArgNames}, RecDict);
false ->
throw({error, flat_format("Type declaration for ~w does not "
"have variables as parameters", [Name])})
diff --git a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
index 4850f3ff0c..173ff3a9f1 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
+++ b/lib/dialyzer/test/small_SUITE_data/results/contracts_with_subtypes
@@ -5,18 +5,18 @@ contracts_with_subtypes.erl:108: The call contracts_with_subtypes:rec_arg({'a',{
contracts_with_subtypes.erl:109: The call contracts_with_subtypes:rec_arg({'b',{'a','b'}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
contracts_with_subtypes.erl:110: The call contracts_with_subtypes:rec_arg({'a',{'b',{'a','b'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
contracts_with_subtypes.erl:111: The call contracts_with_subtypes:rec_arg({'b',{'a',{'b','a'}}}) breaks the contract (Arg) -> 'ok' when is_subtype(Arg,{'a',A} | {'b',B}), is_subtype(A,'a' | {'b',B}), is_subtype(B,'b' | {'a',A})
-contracts_with_subtypes.erl:142: The pattern 1 can never match the type binary() | string()
-contracts_with_subtypes.erl:145: The pattern 'alpha' can never match the type {'ok',_} | {'ok',_,binary() | string()}
-contracts_with_subtypes.erl:147: The pattern 42 can never match the type {'ok',_} | {'ok',_,binary() | string()}
+contracts_with_subtypes.erl:142: The pattern 1 can never match the type string()
+contracts_with_subtypes.erl:145: The pattern 'alpha' can never match the type {'ok',_} | {'ok',_,string()}
+contracts_with_subtypes.erl:147: The pattern 42 can never match the type {'ok',_} | {'ok',_,string()}
contracts_with_subtypes.erl:163: The pattern 'alpha' can never match the type {'ok',X}
contracts_with_subtypes.erl:165: The pattern 42 can never match the type {'ok',X}
contracts_with_subtypes.erl:183: The pattern 'alpha' can never match the type {'ok',X}
contracts_with_subtypes.erl:185: The pattern 42 can never match the type {'ok',X}
-contracts_with_subtypes.erl:202: The pattern 1 can never match the type binary() | string()
-contracts_with_subtypes.erl:205: The pattern {'ok', _} can never match the type {'ok',X,binary() | string()}
-contracts_with_subtypes.erl:206: The pattern 'alpha' can never match the type {'ok',X,binary() | string()}
-contracts_with_subtypes.erl:207: The pattern {'ok', 42} can never match the type {'ok',X,binary() | string()}
-contracts_with_subtypes.erl:208: The pattern 42 can never match the type {'ok',X,binary() | string()}
+contracts_with_subtypes.erl:202: The pattern 1 can never match the type string()
+contracts_with_subtypes.erl:205: The pattern {'ok', _} can never match the type {'ok',X,string()}
+contracts_with_subtypes.erl:206: The pattern 'alpha' can never match the type {'ok',X,string()}
+contracts_with_subtypes.erl:207: The pattern {'ok', 42} can never match the type {'ok',X,string()}
+contracts_with_subtypes.erl:208: The pattern 42 can never match the type {'ok',X,string()}
contracts_with_subtypes.erl:234: Function flat_ets_new_t/0 has no local return
contracts_with_subtypes.erl:235: The call contracts_with_subtypes:flat_ets_new(12,[]) breaks the contract (Name,Options) -> atom() when is_subtype(Name,atom()), is_subtype(Options,[Option]), is_subtype(Option,'set' | 'ordered_set' | 'bag' | 'duplicate_bag' | 'public' | 'protected' | 'private' | 'named_table' | {'keypos',integer()} | {'heir',pid(),term()} | {'heir','none'} | {'write_concurrency',boolean()} | {'read_concurrency',boolean()} | 'compressed')
contracts_with_subtypes.erl:23: Invalid type specification for function contracts_with_subtypes:extract2/0. The success typing is () -> 'something'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/types_arity b/lib/dialyzer/test/small_SUITE_data/results/types_arity
new file mode 100644
index 0000000000..02641bd167
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/types_arity
@@ -0,0 +1,2 @@
+
+types_arity.erl:16: Invalid type specification for function types_arity:test2/0. The success typing is () -> {'node','a','nil','nil'}
diff --git a/lib/dialyzer/test/small_SUITE_data/src/types_arity.erl b/lib/dialyzer/test/small_SUITE_data/src/types_arity.erl
new file mode 100644
index 0000000000..4ddc986ea8
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/types_arity.erl
@@ -0,0 +1,20 @@
+-module(types_arity).
+
+-export([ test1/0
+ , test2/0
+ , test3/0
+ ]).
+
+-export_type([tree/0, tree/1]).
+
+-type tree(T) :: 'nil' | {'node', T, tree(T), tree(T)}.
+-type tree() :: tree(integer()).
+
+-spec test1() -> tree().
+test1() -> {node, 7, nil, nil}.
+
+-spec test2() -> tree().
+test2() -> {node, a, nil, nil}.
+
+-spec test3() -> tree(atom()).
+test3() -> {node, a, nil, nil}.