From b66e75c285cba469c5225f3394da149456d17d16 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 3 Feb 2014 10:27:39 +0100 Subject: Deprecate pre-defined built-in types The types array(), dict(), digraph(), gb_set(), gb_tree(), queue(), set(), and tid() have been deprecated. They will be removed in OTP 18.0. Instead the types array:array(), dict:dict(), digraph:graph(), gb_set:set(), gb_tree:tree(), queue:queue(), sets:set(), and ets:tid() can be used. (Note: it has always been necessary to use ets:tid().) It is allowed in OTP 17.0 to locally re-define the types array(), dict(), and so on. New types array:array/1, dict:dict/2, gb_sets:set/1, gb_trees:tree/2, queue:queue/1, and sets:set/1 have been added. --- bootstrap/lib/stdlib/ebin/erl_lint.beam | Bin 86180 -> 94292 bytes lib/compiler/src/beam_dict.erl | 20 ++- lib/compiler/src/beam_disasm.erl | 11 +- lib/compiler/src/beam_validator.erl | 20 ++- lib/compiler/src/rec_env.erl | 4 +- lib/dialyzer/src/dialyzer_analysis_callgraph.erl | 8 +- lib/dialyzer/src/dialyzer_behaviours.erl | 8 +- lib/dialyzer/src/dialyzer_callgraph.erl | 35 +++-- lib/dialyzer/src/dialyzer_cl.erl | 2 +- lib/dialyzer/src/dialyzer_codeserver.erl | 41 ++--- lib/dialyzer/src/dialyzer_contracts.erl | 22 ++- lib/dialyzer/src/dialyzer_dataflow.erl | 49 +++--- lib/dialyzer/src/dialyzer_dep.erl | 14 +- lib/dialyzer/src/dialyzer_plt.erl | 36 ++--- lib/dialyzer/src/dialyzer_races.erl | 15 +- lib/dialyzer/src/dialyzer_succ_typings.erl | 4 +- lib/dialyzer/src/dialyzer_typesig.erl | 21 ++- lib/dialyzer/src/dialyzer_utils.erl | 20 +-- lib/dialyzer/test/file_utils.erl | 2 +- lib/dialyzer/test/opaque_SUITE_data/results/array | 4 +- lib/dialyzer/test/opaque_SUITE_data/results/dict | 26 ++-- lib/dialyzer/test/opaque_SUITE_data/results/ets | 6 +- lib/dialyzer/test/opaque_SUITE_data/results/ewgi | 6 +- .../test/opaque_SUITE_data/results/inf_loop1 | 2 +- .../test/opaque_SUITE_data/results/inf_loop2 | 2 +- lib/dialyzer/test/opaque_SUITE_data/results/para | 21 +++ lib/dialyzer/test/opaque_SUITE_data/results/queue | 20 +-- lib/dialyzer/test/opaque_SUITE_data/results/simple | 6 +- lib/dialyzer/test/opaque_SUITE_data/results/wings | 14 +- .../test/opaque_SUITE_data/src/dict/dict_use.erl | 2 +- .../test/opaque_SUITE_data/src/ets/ets_use.erl | 4 +- .../test/opaque_SUITE_data/src/ewgi/ewgi.hrl | 2 +- .../test/opaque_SUITE_data/src/ewgi2/ewgi.hrl | 2 +- .../opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl | 4 +- .../test/opaque_SUITE_data/src/inf_loop1.erl | 4 +- .../test/opaque_SUITE_data/src/inf_loop2.erl | 4 +- .../src/multiple_wrong_opaques.erl | 2 +- .../test/opaque_SUITE_data/src/para/para1.erl | 93 ++++++++++++ .../test/opaque_SUITE_data/src/para/para1_adt.erl | 36 +++++ .../test/opaque_SUITE_data/src/para/para2.erl | 123 +++++++++++++++ .../test/opaque_SUITE_data/src/para/para2_adt.erl | 64 ++++++++ .../test/opaque_SUITE_data/src/para/para3.erl | 77 ++++++++++ .../test/opaque_SUITE_data/src/para/para3_adt.erl | 27 ++++ .../opaque_SUITE_data/src/simple/exact_api.erl | 4 +- .../opaque_SUITE_data/src/wings/wings_util.erl | 4 +- .../test/opaque_SUITE_data/src/zoltan_kis2.erl | 2 +- .../results/ets_insert_control_flow3 | 4 +- .../results/ets_insert_control_flow4 | 4 +- .../results/ets_insert_control_flow5 | 8 +- .../test/race_SUITE_data/results/ets_insert_param | 8 +- lib/dialyzer/test/small_SUITE_data/results/predef | 8 + .../test/small_SUITE_data/results/record_construct | 2 +- lib/dialyzer/test/small_SUITE_data/src/predef.erl | 67 +++++++++ lib/dialyzer/test/small_SUITE_data/src/predef2.erl | 56 +++++++ .../test/small_SUITE_data/src/record_construct.erl | 2 +- .../results/lc_warnings | 2 +- lib/edoc/src/edoc_specs.erl | 6 +- lib/eunit/src/eunit_serial.erl | 6 +- lib/hipe/cerl/cerl_closurean.erl | 8 +- lib/hipe/cerl/cerl_messagean.erl | 4 +- lib/hipe/cerl/cerl_typean.erl | 4 +- lib/hipe/cerl/erl_types.erl | 156 +++++++++++-------- lib/hipe/flow/cfg.hrl | 6 +- lib/hipe/flow/cfg.inc | 4 +- lib/hipe/flow/hipe_dominators.erl | 6 +- lib/hipe/flow/liveness.inc | 6 +- lib/hipe/icode/hipe_icode_callgraph.erl | 4 +- lib/hipe/icode/hipe_icode_cfg.erl | 6 +- lib/hipe/icode/hipe_icode_coordinator.erl | 8 +- lib/hipe/icode/hipe_icode_exceptions.erl | 8 +- lib/hipe/icode/hipe_icode_fp.erl | 6 +- lib/hipe/icode/hipe_icode_instruction_counter.erl | 5 +- lib/hipe/icode/hipe_icode_range.erl | 10 +- lib/hipe/icode/hipe_icode_ssa.erl | 4 +- lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl | 16 +- lib/hipe/icode/hipe_icode_type.erl | 6 +- lib/hipe/misc/hipe_consttab.erl | 8 +- lib/hipe/misc/hipe_consttab.hrl | 4 +- lib/hipe/misc/hipe_pack_constants.erl | 4 +- lib/hipe/misc/hipe_sdi.erl | 15 +- lib/hipe/regalloc/hipe_ig_moves.erl | 4 +- lib/hipe/ssa/hipe_ssa_const_prop.inc | 10 +- lib/hipe/util/hipe_digraph.erl | 8 +- lib/hipe/util/hipe_dot.erl | 6 +- lib/hipe/util/hipe_vectors.hrl | 4 +- lib/inets/src/http_client/httpc_handler.erl | 6 +- lib/kernel/src/rpc.erl | 4 +- lib/ssl/src/ssl_connection.hrl | 4 +- lib/stdlib/doc/src/array.xml | 16 +- lib/stdlib/doc/src/dict.xml | 10 +- lib/stdlib/doc/src/digraph.xml | 4 +- lib/stdlib/doc/src/gb_sets.xml | 90 ++++++----- lib/stdlib/doc/src/gb_trees.xml | 46 +++--- lib/stdlib/doc/src/queue.xml | 10 +- lib/stdlib/doc/src/sets.xml | 10 +- lib/stdlib/src/array.erl | 102 +++++++------ lib/stdlib/src/dict.erl | 124 +++++++-------- lib/stdlib/src/digraph.erl | 98 ++++++------ lib/stdlib/src/digraph_utils.erl | 44 +++--- lib/stdlib/src/epp.erl | 4 +- lib/stdlib/src/erl_lint.erl | 83 ++++++---- lib/stdlib/src/ets.erl | 4 +- lib/stdlib/src/gb_sets.erl | 167 ++++++++++----------- lib/stdlib/src/gb_trees.erl | 139 +++++++---------- lib/stdlib/src/queue.erl | 75 ++++----- lib/stdlib/src/sets.erl | 114 +++++++------- lib/stdlib/src/sofs.erl | 10 +- lib/stdlib/src/supervisor.erl | 47 +++--- lib/stdlib/test/erl_lint_SUITE.erl | 30 +++- lib/stdlib/test/erl_lint_SUITE_data/predef.erl | 67 +++++++++ lib/stdlib/test/erl_lint_SUITE_data/predef2.erl | 56 +++++++ lib/syntax_tools/src/erl_syntax_lib.erl | 10 +- lib/syntax_tools/src/erl_tidy.erl | 14 +- lib/syntax_tools/src/igor.erl | 20 +-- lib/tools/src/xref_compiler.erl | 4 +- lib/tools/src/xref_utils.erl | 4 +- lib/typer/src/typer.erl | 4 +- 117 files changed, 1830 insertions(+), 986 deletions(-) create mode 100644 lib/dialyzer/test/opaque_SUITE_data/results/para create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para1.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para1_adt.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para2.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para2_adt.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para3.erl create mode 100644 lib/dialyzer/test/opaque_SUITE_data/src/para/para3_adt.erl create mode 100644 lib/dialyzer/test/small_SUITE_data/results/predef create mode 100644 lib/dialyzer/test/small_SUITE_data/src/predef.erl create mode 100644 lib/dialyzer/test/small_SUITE_data/src/predef2.erl create mode 100644 lib/stdlib/test/erl_lint_SUITE_data/predef.erl create mode 100644 lib/stdlib/test/erl_lint_SUITE_data/predef2.erl diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam index 301785992c..98f7a236ae 100644 Binary files a/bootstrap/lib/stdlib/ebin/erl_lint.beam and b/bootstrap/lib/stdlib/ebin/erl_lint.beam differ diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl index 212b9fb03a..ea51673fa3 100644 --- a/lib/compiler/src/beam_dict.erl +++ b/lib/compiler/src/beam_dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2013. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -29,16 +29,24 @@ -type label() :: non_neg_integer(). +-type index() :: non_neg_integer(). + +-type atom_tab() :: gb_trees:tree(atom(), index()). +-type import_tab() :: gb_trees:tree(mfa(), index()). +-type fname_tab() :: gb_trees:tree(Name :: term(), index()). +-type line_tab() :: gb_trees:tree({Fname :: index(), Line :: term()}, index()). +-type literal_tab() :: dict:dict(Literal :: term(), index()). + -record(asm, - {atoms = gb_trees:empty() :: gb_tree(), %{Atom,Index} + {atoms = gb_trees:empty() :: atom_tab(), exports = [] :: [{label(), arity(), label()}], locals = [] :: [{label(), arity(), label()}], - imports = gb_trees:empty() :: gb_tree(), %{{M,F,A},Index} + imports = gb_trees:empty() :: import_tab(), strings = <<>> :: binary(), %String pool lambdas = [], %[{...}] - literals = dict:new() :: dict(), %Format: {Literal,Number} - fnames = gb_trees:empty() :: gb_tree(), %{Name,Index} - lines = gb_trees:empty() :: gb_tree(), %{{Fname,Line},Index} + literals = dict:new() :: literal_tab(), + fnames = gb_trees:empty() :: fname_tab(), + lines = gb_trees:empty() :: line_tab(), num_lines = 0 :: non_neg_integer(), %Number of line instructions next_import = 0 :: non_neg_integer(), string_offset = 0 :: non_neg_integer(), diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl index 363989f4c9..4bdfe4e0c2 100644 --- a/lib/compiler/src/beam_disasm.erl +++ b/lib/compiler/src/beam_disasm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,7 +37,8 @@ %%----------------------------------------------------------------------- --type literals() :: 'none' | gb_tree(). +-type index() :: non_neg_integer(). +-type literals() :: 'none' | gb_trees:tree(index(), term()). -type symbolic_tag() :: 'a' | 'f' | 'h' | 'i' | 'u' | 'x' | 'y' | 'z'. -type disasm_tag() :: symbolic_tag() | 'fr' | 'atom' | 'float' | 'literal'. -type disasm_term() :: 'nil' | {disasm_tag(), _}. @@ -216,7 +217,8 @@ optional_chunk(F, ChunkTag) -> %%----------------------------------------------------------------------- -type l_info() :: {non_neg_integer(), {_,_,_,_,_,_}}. --spec beam_disasm_lambdas('none' | binary(), gb_tree()) -> 'none' | [l_info()]. +-spec beam_disasm_lambdas('none' | binary(), gb_trees:tree(index(), _)) -> + 'none' | [l_info()]. beam_disasm_lambdas(none, _) -> none; beam_disasm_lambdas(<<_:32,Tab/binary>>, Atoms) -> @@ -435,7 +437,8 @@ decode_arg([B|Bs]) -> decode_int(Tag, B, Bs) end. --spec decode_arg([byte(),...], gb_tree(), literals()) -> {disasm_term(), [byte()]}. +-spec decode_arg([byte(),...], gb_trees:tree(index(), _), literals()) -> + {disasm_term(), [byte()]}. decode_arg([B|Bs0], Atoms, Literals) -> Tag = decode_tag(B band 2#111), diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 7e1324cf61..9d5563d13b 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -213,9 +213,12 @@ validate_error_1(Error, Module, Name, Ar) -> {{Module,Name,Ar}, {internal_error,'_',{Error,erlang:get_stacktrace()}}}. +-type index() :: non_neg_integer(). +-type reg_tab() :: gb_trees:tree(index(), 'none' | {'value', _}). + -record(st, %Emulation state - {x=init_regs(0, term) :: gb_tree(), %x register info. - y=init_regs(0, initialized) :: gb_tree(), %y register info. + {x=init_regs(0, term) :: reg_tab(),%x register info. + y=init_regs(0, initialized) :: reg_tab(),%y register info. f=init_fregs(), % numy=none, %Number of y registers. h=0, %Available heap size. @@ -227,11 +230,16 @@ validate_error_1(Error, Module, Name, Ar) -> setelem=false %Previous instruction was setelement/3. }). +-type label() :: integer(). +-type label_set() :: gb_sets:set(label()). +-type branched_tab() :: gb_trees:tree(label(), #st{}). +-type ft_tab() :: gb_trees:tree(). + -record(vst, %Validator state {current=none :: #st{} | 'none', %Current state - branched=gb_trees:empty() :: gb_tree(), %States at jumps - labels=gb_sets:empty() :: gb_set(), %All defined labels - ft=gb_trees:empty() :: gb_tree() %Some other functions + branched=gb_trees:empty() :: branched_tab(), %States at jumps + labels=gb_sets:empty() :: label_set(), %All defined labels + ft=gb_trees:empty() :: ft_tab() %Some other functions % in the module (those that start with bs_start_match2). }). diff --git a/lib/compiler/src/rec_env.erl b/lib/compiler/src/rec_env.erl index 31a1f8b0b7..ddcd461bc0 100644 --- a/lib/compiler/src/rec_env.erl +++ b/lib/compiler/src/rec_env.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -95,7 +95,7 @@ test_1(_,0, Env) -> %% ===================================================================== %% @type environment(). An abstract environment. --type mapping() :: {'map', dict()} | {'rec', dict(), dict()}. +-type mapping() :: {'map', dict:dict()} | {'rec', dict:dict(), dict:dict()}. -type environment() :: [mapping(),...]. %% ===================================================================== diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 0fbaf1d47c..3de020cb01 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -2,7 +2,7 @@ %%-------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -39,6 +39,8 @@ one_file_result/0, compile_result/0]). +-export_type([no_warn_unused/0]). + -include("dialyzer.hrl"). -record(analysis_state, @@ -48,7 +50,7 @@ defines = [] :: [dial_define()], doc_plt :: dialyzer_plt:plt(), include_dirs = [] :: [file:filename()], - no_warn_unused :: set(), + no_warn_unused :: no_warn_unused(), parent :: pid(), plt :: dialyzer_plt:plt(), start_from = byte_code :: start_from(), @@ -59,6 +61,8 @@ -record(server_state, {parent :: pid(), legal_warnings :: [dial_warn_tag()]}). +-type no_warn_unused() :: sets:set(mfa()). + %%-------------------------------------------------------------------- %% Main %%-------------------------------------------------------------------- diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl index 2b9a69ce77..1d458b49fc 100644 --- a/lib/dialyzer/src/dialyzer_behaviours.erl +++ b/lib/dialyzer/src/dialyzer_behaviours.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,15 +40,17 @@ -type behaviour() :: atom(). +-type rectab() :: erl_types:type_table(). + -record(state, {plt :: dialyzer_plt:plt(), codeserver :: dialyzer_codeserver:codeserver(), filename :: file:filename(), behlines :: [{behaviour(), non_neg_integer()}], - records :: dict()}). + records :: rectab()}). %%-------------------------------------------------------------------- --spec check_callbacks(module(), [{cerl:cerl(), cerl:cerl()}], dict(), +-spec check_callbacks(module(), [{cerl:cerl(), cerl:cerl()}], rectab(), dialyzer_plt:plt(), dialyzer_codeserver:codeserver()) -> [dial_warning()]. diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index bc32110751..00b01fbd36 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -64,14 +64,16 @@ put_named_tables/2, put_public_tables/2, put_behaviour_api_calls/2, get_behaviour_api_calls/1, dispose_race_server/1, duplicate/1]). --export_type([callgraph/0, mfa_or_funlbl/0, callgraph_edge/0]). +-export_type([callgraph/0, mfa_or_funlbl/0, callgraph_edge/0, mod_deps/0]). -include("dialyzer.hrl"). %%---------------------------------------------------------------------- -type scc() :: [mfa_or_funlbl()]. --type mfa_calls() :: [{mfa_or_funlbl(), mfa_or_funlbl()}]. +-type mfa_call() :: {mfa_or_funlbl(), mfa_or_funlbl()}. +-type mfa_calls() :: [mfa_call()]. +-type mod_deps() :: dict:dict(module(), [module()]). %%----------------------------------------------------------------------------- %% A callgraph is a directed graph where the nodes are functions and a @@ -93,7 +95,7 @@ %% whenever applicable. %%----------------------------------------------------------------------------- --record(callgraph, {digraph = digraph:new() :: digraph(), +-record(callgraph, {digraph = digraph:new() :: digraph:graph(), active_digraph :: active_digraph(), esc :: ets:tid(), letrec_map :: ets:tid(), @@ -105,7 +107,7 @@ race_detection = false :: boolean(), race_data_server = new_race_data_server() :: pid()}). --record(race_data_state, {race_code = dict:new() :: dict(), +-record(race_data_state, {race_code = dict:new() :: dict:dict(), public_tables = [] :: [label()], named_tables = [] :: [string()], beh_api_calls = [] :: [{mfa(), mfa()}]}). @@ -114,7 +116,7 @@ -type callgraph() :: #callgraph{}. --type active_digraph() :: {'d', digraph()} | {'e', ets:tid(), ets:tid()}. +-type active_digraph() :: {'d', digraph:graph()} | {'e', ets:tid(), ets:tid()}. %%---------------------------------------------------------------------- @@ -222,7 +224,10 @@ non_local_calls(#callgraph{digraph = DG}) -> Edges = digraph_edges(DG), find_non_local_calls(Edges, sets:new()). --spec find_non_local_calls([{mfa_or_funlbl(), mfa_or_funlbl()}], set()) -> mfa_calls(). +-type call_tab() :: sets:set(mfa_call()). + +-spec find_non_local_calls([{mfa_or_funlbl(), mfa_or_funlbl()}], call_tab()) -> + mfa_calls(). find_non_local_calls([{{M,_,_}, {M,_,_}}|Left], Set) -> find_non_local_calls(Left, Set); @@ -267,7 +272,7 @@ get_required_by(SCC, #callgraph{active_digraph = {'d', DG}}) -> modules(#callgraph{digraph = DG}) -> ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]). --spec module_postorder(callgraph()) -> {[module()], {'d', digraph()}}. +-spec module_postorder(callgraph()) -> {[module()], {'d', digraph:graph()}}. module_postorder(#callgraph{digraph = DG}) -> Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)), @@ -287,7 +292,7 @@ edge_fold(_, Set) -> Set. %% The module deps of a module are modules that depend on the module --spec module_deps(callgraph()) -> dict(). +-spec module_deps(callgraph()) -> mod_deps(). module_deps(#callgraph{digraph = DG}) -> Edges = lists:foldl(fun edge_fold/2, sets:new(), digraph_edges(DG)), @@ -301,7 +306,7 @@ module_deps(#callgraph{digraph = DG}) -> digraph_delete(MDG), dict:from_list(Deps). --spec strip_module_deps(dict(), set()) -> dict(). +-spec strip_module_deps(mod_deps(), sets:set(module())) -> mod_deps(). strip_module_deps(ModDeps, StripSet) -> FilterFun1 = fun(Val) -> not sets:is_element(Val, StripSet) end, @@ -575,7 +580,7 @@ digraph_reaching_subgraph(Funs, DG) -> %% Races %%---------------------------------------------------------------------- --spec renew_race_info(callgraph(), dict(), [label()], [string()]) -> +-spec renew_race_info(callgraph(), dict:dict(), [label()], [string()]) -> callgraph(). renew_race_info(#callgraph{race_data_server = RaceDataServer} = CG, @@ -641,7 +646,7 @@ duplicate(#callgraph{race_data_server = RaceDataServer} = Callgraph) -> dispose_race_server(#callgraph{race_data_server = RaceDataServer}) -> race_data_server_cast(stop, RaceDataServer). --spec get_digraph(callgraph()) -> digraph(). +-spec get_digraph(callgraph()) -> digraph:graph(). get_digraph(#callgraph{digraph = Digraph}) -> Digraph. @@ -656,7 +661,7 @@ get_named_tables(#callgraph{race_data_server = RaceDataServer}) -> get_public_tables(#callgraph{race_data_server = RaceDataServer}) -> race_data_server_call(get_public_tables, RaceDataServer). --spec get_race_code(callgraph()) -> dict(). +-spec get_race_code(callgraph()) -> dict:dict(). get_race_code(#callgraph{race_data_server = RaceDataServer}) -> race_data_server_call(get_race_code, RaceDataServer). @@ -677,12 +682,12 @@ race_code_new(#callgraph{race_data_server = RaceDataServer} = CG) -> ok = race_data_server_cast(race_code_new, RaceDataServer), CG. --spec put_digraph(digraph(), callgraph()) -> callgraph(). +-spec put_digraph(digraph:graph(), callgraph()) -> callgraph(). put_digraph(Digraph, Callgraph) -> Callgraph#callgraph{digraph = Digraph}. --spec put_race_code(dict(), callgraph()) -> callgraph(). +-spec put_race_code(dict:dict(), callgraph()) -> callgraph(). put_race_code(RaceCode, #callgraph{race_data_server = RaceDataServer} = CG) -> ok = race_data_server_cast({put_race_code, RaceCode}, RaceDataServer), diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index cda801bf6c..3e68d64d53 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -40,7 +40,7 @@ external_calls = [] :: [mfa()], external_types = [] :: [mfa()], legal_warnings = ordsets:new() :: [dial_warn_tag()], - mod_deps = dict:new() :: dict(), + mod_deps = dict:new() :: dialyzer_callgraph:mod_deps(), output = standard_io :: io:device(), output_format = formatted :: format(), filename_opt = basename :: fopt(), diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index 216e06219c..aab3d6add6 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -64,6 +64,12 @@ -type dict_ets() :: ets:tid(). -type set_ets() :: ets:tid(). +-type types() :: erl_types:type_table(). +-type mod_records() :: dict:dict(module(), types()). + +-type contracts() :: dict:dict(mfa(),dialyzer_contracts:file_contract()). +-type mod_contracts() :: dict:dict(module(), contracts()). + -record(codeserver, {next_core_label = 0 :: label(), code :: dict_ets(), exported_types :: set_ets(), % set(mfa()) @@ -160,12 +166,12 @@ insert(Mod, ModCode, CS) -> true = ets:insert(CS#codeserver.code, [ModEntry|Funs]), CS. --spec get_temp_exported_types(codeserver()) -> set(). +-spec get_temp_exported_types(codeserver()) -> sets:set(mfa()). get_temp_exported_types(#codeserver{temp_exported_types = TempExpTypes}) -> ets_set_to_set(TempExpTypes). --spec insert_temp_exported_types(set(), codeserver()) -> codeserver(). +-spec insert_temp_exported_types(sets:set(mfa()), codeserver()) -> codeserver(). insert_temp_exported_types(Set, CS) -> TempExportedTypes = CS#codeserver.temp_exported_types, @@ -183,17 +189,17 @@ insert_exports(List, #codeserver{exports = Exports} = CS) -> is_exported(MFA, #codeserver{exports = Exports}) -> ets_set_is_element(MFA, Exports). --spec get_exported_types(codeserver()) -> set(). % set(mfa()) +-spec get_exported_types(codeserver()) -> sets:set(mfa()). get_exported_types(#codeserver{exported_types = ExpTypes}) -> ets_set_to_set(ExpTypes). --spec get_exports(codeserver()) -> set(). % set(mfa()) +-spec get_exports(codeserver()) -> sets:set(mfa()). get_exports(#codeserver{exports = Exports}) -> ets_set_to_set(Exports). --spec finalize_exported_types(set(), codeserver()) -> codeserver(). +-spec finalize_exported_types(sets:set(mfa()), codeserver()) -> codeserver(). finalize_exported_types(Set, CS) -> ExportedTypes = ets_read_concurrent_table(dialyzer_codeserver_exported_types), @@ -222,7 +228,7 @@ get_next_core_label(#codeserver{next_core_label = NCL}) -> set_next_core_label(NCL, CS) -> CS#codeserver{next_core_label = NCL}. --spec lookup_mod_records(atom(), codeserver()) -> dict(). +-spec lookup_mod_records(atom(), codeserver()) -> types(). lookup_mod_records(Mod, #codeserver{records = RecDict}) when is_atom(Mod) -> case ets_dict_find(Mod, RecDict) of @@ -230,12 +236,12 @@ lookup_mod_records(Mod, #codeserver{records = RecDict}) when is_atom(Mod) -> {ok, Dict} -> Dict end. --spec get_records(codeserver()) -> dict(). +-spec get_records(codeserver()) -> mod_records(). get_records(#codeserver{records = RecDict}) -> ets_dict_to_dict(RecDict). --spec store_temp_records(atom(), dict(), codeserver()) -> codeserver(). +-spec store_temp_records(module(), types(), codeserver()) -> codeserver(). store_temp_records(Mod, Dict, #codeserver{temp_records = TempRecDict} = CS) when is_atom(Mod) -> @@ -244,12 +250,12 @@ store_temp_records(Mod, Dict, #codeserver{temp_records = TempRecDict} = CS) false -> CS#codeserver{temp_records = ets_dict_store(Mod, Dict, TempRecDict)} end. --spec get_temp_records(codeserver()) -> dict(). +-spec get_temp_records(codeserver()) -> mod_records(). get_temp_records(#codeserver{temp_records = TempRecDict}) -> ets_dict_to_dict(TempRecDict). --spec set_temp_records(dict(), codeserver()) -> codeserver(). +-spec set_temp_records(mod_records(), codeserver()) -> codeserver(). set_temp_records(Dict, CS) -> true = ets:delete(CS#codeserver.temp_records), @@ -257,7 +263,7 @@ set_temp_records(Dict, CS) -> true = ets_dict_store_dict(Dict, TempRecords), CS#codeserver{temp_records = TempRecords}. --spec finalize_records(dict(), codeserver()) -> codeserver(). +-spec finalize_records(mod_records(), codeserver()) -> codeserver(). finalize_records(Dict, CS) -> true = ets:delete(CS#codeserver.temp_records), @@ -265,7 +271,7 @@ finalize_records(Dict, CS) -> true = ets_dict_store_dict(Dict, Records), CS#codeserver{records = Records, temp_records = clean}. --spec lookup_mod_contracts(atom(), codeserver()) -> dict(). +-spec lookup_mod_contracts(atom(), codeserver()) -> contracts(). lookup_mod_contracts(Mod, #codeserver{contracts = ContDict}) when is_atom(Mod) -> @@ -284,7 +290,7 @@ get_contract_pair(Key, ContDict) -> lookup_mfa_contract(MFA, #codeserver{contracts = ContDict}) -> ets_dict_find(MFA, ContDict). --spec get_contracts(codeserver()) -> dict(). +-spec get_contracts(codeserver()) -> mod_contracts(). get_contracts(#codeserver{contracts = ContDict}) -> ets_dict_to_dict(ContDict). @@ -294,7 +300,7 @@ get_contracts(#codeserver{contracts = ContDict}) -> get_callbacks(#codeserver{callbacks = CallbDict}) -> ets:tab2list(CallbDict). --spec store_temp_contracts(atom(), dict(), dict(), codeserver()) -> +-spec store_temp_contracts(module(), contracts(), contracts(), codeserver()) -> codeserver(). store_temp_contracts(Mod, SpecDict, CallbackDict, @@ -313,13 +319,14 @@ store_temp_contracts(Mod, SpecDict, CallbackDict, CS1#codeserver{temp_callbacks = ets_dict_store(Mod, CallbackDict, Cb)} end. --spec get_temp_contracts(codeserver()) -> {dict(), dict()}. +-spec get_temp_contracts(codeserver()) -> {mod_contracts(), mod_contracts()}. get_temp_contracts(#codeserver{temp_contracts = TempContDict, temp_callbacks = TempCallDict}) -> {ets_dict_to_dict(TempContDict), ets_dict_to_dict(TempCallDict)}. --spec finalize_contracts(dict(), dict(), codeserver()) -> codeserver(). +-spec finalize_contracts(mod_contracts(), mod_contracts(), codeserver()) -> + codeserver(). finalize_contracts(SpecDict, CallbackDict, CS) -> Contracts = ets_read_concurrent_table(dialyzer_codeserver_contracts), diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 5b2c52b2d0..46eaeaa303 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -52,7 +52,7 @@ %% to expand records and/or remote types that they might contain. %%----------------------------------------------------------------------- --type tmp_contract_fun() :: fun((set(), dict()) -> contract_pair()). +-type tmp_contract_fun() :: fun((sets:set(mfa()), types()) -> contract_pair()). -record(tmp_contract, {contract_funs = [] :: [tmp_contract_fun()], forms = [] :: [{_, _}]}). @@ -163,8 +163,10 @@ process_contract_remote_types(CodeServer) -> -type opaques() :: [erl_types:erl_type()] | 'universe'. -type opaques_fun() :: fun((module()) -> opaques()). +-type fun_types() :: dict:dict(label(), erl_types:type_table()). + -spec check_contracts([{mfa(), file_contract()}], - dialyzer_callgraph:callgraph(), dict(), + dialyzer_callgraph:callgraph(), fun_types(), opaques_fun()) -> plt_contracts(). check_contracts(Contracts, Callgraph, FunTypes, FindOpaques) -> @@ -292,7 +294,8 @@ is_not_nil_list(Type) -> erl_types:t_is_list(Type) andalso not erl_types:t_is_nil(Type). %% This is the heart of the "range function" --spec process_contracts([contract_pair()], [erl_types:erl_type()]) -> erl_types:erl_type(). +-spec process_contracts([contract_pair()], [erl_types:erl_type()]) -> + erl_types:erl_type(). process_contracts(OverContracts, Args) -> process_contracts(OverContracts, Args, erl_types:t_none()). @@ -307,7 +310,8 @@ process_contracts([OverContract|Left], Args, AccRange) -> process_contracts([], _Args, AccRange) -> AccRange. --spec process_contract(contract_pair(), [erl_types:erl_type()]) -> 'error' | {'ok', erl_types:erl_type()}. +-spec process_contract(contract_pair(), [erl_types:erl_type()]) -> + 'error' | {'ok', erl_types:erl_type()}. process_contract({Contract, Constraints}, CallTypes0) -> CallTypesFun = erl_types:t_fun(CallTypes0, erl_types:t_any()), @@ -343,8 +347,11 @@ solve_constraints(Contract, Call, Constraints) -> %% ?debug("Inf: ~s\n", [erl_types:t_to_string(Inf)]), %% erl_types:t_assign_variables_to_subtype(Contract, Inf). +-type contracts() :: dict:dict(mfa(),dialyzer_contracts:file_contract()). + %% Checks the contracts for functions that are not implemented --spec contracts_without_fun(dict(), [_], dialyzer_callgraph:callgraph()) -> [dial_warning()]. +-spec contracts_without_fun(contracts(), [_], dialyzer_callgraph:callgraph()) -> + [dial_warning()]. contracts_without_fun(Contracts, AllFuns0, Callgraph) -> AllFuns1 = [{dialyzer_callgraph:lookup_name(Label, Callgraph), Arity} @@ -377,7 +384,10 @@ insert_constraints([{subtype, Type1, Type2}|Left], Dict) -> end; insert_constraints([], Dict) -> Dict. --spec store_tmp_contract(mfa(), file_line(), [_], dict(), dict()) -> dict(). +-type types() :: erl_types:type_table(). + +-spec store_tmp_contract(mfa(), file_line(), [_], contracts(), types()) -> + contracts(). store_tmp_contract(MFA, FileLine, TypeSpec, SpecDict, RecordsDict) -> %% io:format("contract from form: ~p\n", [TypeSpec]), diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index b00e0465e0..692684cd99 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -86,39 +86,53 @@ %%-------------------------------------------------------------------- +-type type() :: erl_types:erl_type(). +-type types() :: erl_types:type_table(). + -define(no_arg, no_arg). -define(TYPE_LIMIT, 3). -record(state, {callgraph :: dialyzer_callgraph:callgraph(), - envs :: dict(), - fun_tab :: dict(), + envs :: env_tab(), + fun_tab :: fun_tab(), plt :: dialyzer_plt:plt(), - opaques :: [erl_types:erl_type()], + opaques :: [type()], races = dialyzer_races:new() :: dialyzer_races:races(), - records = dict:new() :: dict(), - tree_map :: dict(), + records = dict:new() :: types(), + tree_map :: dict:dict(label(), cerl:cerl()), warning_mode = false :: boolean(), warnings = [] :: [dial_warning()], - work :: {[_], [_], set()}, + work :: {[_], [_], sets:set()}, module :: module() }). --record(map, {dict = dict:new() :: dict(), - subst = dict:new() :: dict(), +-record(map, {dict = dict:new() :: type_tab(), + subst = dict:new() :: subst_tab(), modified = [] :: [Key :: term()], modified_stack = [] :: [{[Key :: term()],reference()}], ref = undefined :: reference() | undefined}). +-type nowarn() :: dialyzer_analysis_callgraph:no_warn_unused(). +-type env_tab() :: dict:dict(label(), #map{}). +-type fun_entry() :: {Args :: [type()], RetType :: type()}. +-type fun_tab() :: dict:dict('top' | label(), + {'not_handled', fun_entry()} | fun_entry()). +-type key() :: label() | cerl:cerl(). +-type type_tab() :: dict:dict(key(), type()). +-type subst_tab() :: dict:dict(key(), cerl:cerl()). + %% Exported Types -opaque state() :: #state{}. %%-------------------------------------------------------------------- +-type fun_types() :: dict:dict(label(), type()). + -spec get_warnings(cerl:c_module(), dialyzer_plt:plt(), - dialyzer_callgraph:callgraph(), dict(), set()) -> - {[dial_warning()], dict()}. + dialyzer_callgraph:callgraph(), types(), nowarn()) -> + {[dial_warning()], fun_types()}. get_warnings(Tree, Plt, Callgraph, Records, NoWarnUnused) -> State1 = analyze_module(Tree, Plt, Callgraph, Records, true), @@ -129,7 +143,8 @@ get_warnings(Tree, Plt, Callgraph, Records, NoWarnUnused) -> {State4#state.warnings, state__all_fun_types(State4)}. -spec get_fun_types(cerl:c_module(), dialyzer_plt:plt(), - dialyzer_callgraph:callgraph(), dict()) -> dict(). + dialyzer_callgraph:callgraph(), + types()) -> fun_types(). get_fun_types(Tree, Plt, Callgraph, Records) -> State = analyze_module(Tree, Plt, Callgraph, Records, false), @@ -2299,7 +2314,7 @@ bind_guard_list([], Map, _Env, _Eval, _State, Acc) -> -type eval() :: 'pos' | 'neg' | 'dont_know'. --spec signal_guard_fail(eval(), cerl:c_call(), [erl_types:erl_type()], +-spec signal_guard_fail(eval(), cerl:c_call(), [type()], state()) -> no_return(). signal_guard_fail(Eval, Guard, ArgTypes, State) -> @@ -3161,7 +3176,7 @@ state__get_callgraph(#state{callgraph = Callgraph}) -> state__get_races(#state{races = Races}) -> Races. --spec state__get_records(state()) -> dict(). +-spec state__get_records(state()) -> types(). state__get_records(#state{records = Records}) -> Records. @@ -3260,7 +3275,7 @@ get_file([_|Tail]) -> get_file(Tail). is_compiler_generated(Ann) -> lists:member(compiler_generated, Ann) orelse (get_line(Ann) < 1). --spec format_args([cerl:cerl()], [erl_types:erl_type()], state()) -> +-spec format_args([cerl:cerl()], [type()], state()) -> nonempty_string(). format_args([], [], _State) -> @@ -3295,17 +3310,17 @@ format_arg(Arg) -> Default end. --spec format_type(erl_types:erl_type(), state()) -> string(). +-spec format_type(type(), state()) -> string(). format_type(Type, #state{records = R}) -> t_to_string(Type, R). --spec format_field_diffs(erl_types:erl_type(), state()) -> string(). +-spec format_field_diffs(type(), state()) -> string(). format_field_diffs(RecConstruction, #state{records = R}) -> erl_types:record_field_diffs_to_string(RecConstruction, R). --spec format_sig_args(erl_types:erl_type(), state()) -> string(). +-spec format_sig_args(type(), state()) -> string(). format_sig_args(Type, #state{opaques = Opaques} = State) -> SigArgs = t_fun_args(Type, Opaques), diff --git a/lib/dialyzer/src/dialyzer_dep.erl b/lib/dialyzer/src/dialyzer_dep.erl index a81ea1a98b..5c1245ae47 100644 --- a/lib/dialyzer/src/dialyzer_dep.erl +++ b/lib/dialyzer/src/dialyzer_dep.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -59,7 +59,7 @@ %% -spec analyze(cerl:c_module()) -> - {dict(), ordset('external' | label()), dict(), dict()}. + {dict:dict(), ordset('external' | label()), dict:dict(), dict:dict()}. analyze(Tree) -> %% io:format("Handling ~w\n", [cerl:atom_val(cerl:module_name(Tree))]), @@ -309,7 +309,7 @@ primop(Tree, ArgFuns, State) -> %% Set %% --record(set, {set :: set()}). +-record(set, {set :: sets:set()}). set__singleton(Val) -> #set{set = sets:add_element(Val, sets:new())}. @@ -478,11 +478,11 @@ all_vars(Tree, AccIn) -> -type local_set() :: 'none' | #set{}. --record(state, {deps :: dict(), +-record(state, {deps :: dict:dict(), esc :: local_set(), - call :: dict(), - arities :: dict(), - letrecs :: dict()}). + call :: dict:dict(), + arities :: dict:dict(), + letrecs :: dict:dict()}). state__new(Tree) -> Exports = set__from_list([X || X <- cerl:module_exports(Tree)]), diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl index 5f64099210..63798f44b1 100644 --- a/lib/dialyzer/src/dialyzer_plt.erl +++ b/lib/dialyzer/src/dialyzer_plt.erl @@ -2,7 +2,7 @@ %%---------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -67,7 +67,7 @@ %%---------------------------------------------------------------------- --type mod_deps() :: dict(). +-type mod_deps() :: dialyzer_callgraph:mod_deps(). -type deep_string() :: string() | [deep_string()]. @@ -80,11 +80,11 @@ %%---------------------------------------------------------------------- --record(plt, {info = table_new() :: dict(), - types = table_new() :: dict(), - contracts = table_new() :: dict(), - callbacks = table_new() :: dict(), - exported_types = sets:new() :: set()}). +-record(plt, {info = table_new() :: dict:dict(), + types = table_new() :: dict:dict(), + contracts = table_new() :: dict:dict(), + callbacks = table_new() :: dict:dict(), + exported_types = sets:new() :: sets:set()}). -record(mini_plt, {info :: ets:tid(), contracts :: ets:tid(), @@ -96,15 +96,15 @@ -include("dialyzer.hrl"). -type file_md5() :: {file:filename(), binary()}. --type plt_info() :: {[file_md5()], dict()}. +-type plt_info() :: {[file_md5()], dict:dict()}. -record(file_plt, {version = "" :: string(), file_md5_list = [] :: [file_md5()], - info = dict:new() :: dict(), - contracts = dict:new() :: dict(), - callbacks = dict:new() :: dict(), - types = dict:new() :: dict(), - exported_types = sets:new() :: set(), + info = dict:new() :: dict:dict(), + contracts = dict:new() :: dict:dict(), + callbacks = dict:new() :: dict:dict(), + types = dict:new() :: dict:dict(), + exported_types = sets:new() :: sets:set(), mod_deps :: mod_deps(), implementation_md5 = [] :: [file_md5()]}). @@ -184,22 +184,22 @@ lookup(Plt, Label) when is_integer(Label) -> lookup_1(#mini_plt{info = Info}, MFAorLabel) -> ets_table_lookup(Info, MFAorLabel). --spec insert_types(plt(), dict()) -> plt(). +-spec insert_types(plt(), dict:dict()) -> plt(). insert_types(PLT, Rec) -> PLT#plt{types = Rec}. --spec insert_exported_types(plt(), set()) -> plt(). +-spec insert_exported_types(plt(), sets:set()) -> plt(). insert_exported_types(PLT, Set) -> PLT#plt{exported_types = Set}. --spec get_types(plt()) -> dict(). +-spec get_types(plt()) -> dict:dict(). get_types(#plt{types = Types}) -> Types. --spec get_exported_types(plt()) -> set(). +-spec get_exported_types(plt()) -> sets:set(). get_exported_types(#plt{exported_types = ExpTypes}) -> ExpTypes. @@ -211,7 +211,7 @@ get_exported_types(#plt{exported_types = ExpTypes}) -> lookup_module(#plt{info = Info}, M) when is_atom(M) -> table_lookup_module(Info, M). --spec all_modules(plt()) -> set(). +-spec all_modules(plt()) -> sets:set(). all_modules(#plt{info = Info, contracts = Cs}) -> sets:union(table_all_modules(Info), table_all_modules(Cs)). diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 2aa8343bce..48fcde8014 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -98,14 +98,14 @@ def_vars :: [core_vars()], arg_types :: [erl_types:erl_type()], call_vars :: [core_vars()], - var_map :: dict()}). + var_map :: dict:dict()}). -record(dep_call, {call_name :: dep_calls(), args :: args(), arg_types :: [erl_types:erl_type()], vars :: [core_vars()], state :: _, %% XXX: recursive file_line :: file_line(), - var_map :: dict()}). + var_map :: dict:dict()}). -record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(), callee :: dialyzer_callgraph:mfa_or_funlbl(), arg_types :: [erl_types:erl_type()], @@ -114,7 +114,7 @@ arg :: var_to_map1()}). -record(warn_call, {call_name :: warn_calls(), args :: args(), - var_map :: dict()}). + var_map :: dict:dict()}). -type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}. -type code() :: [#dep_call{} | #fun_call{} | #warn_call{} | @@ -1565,7 +1565,7 @@ any_args(StrList) -> end end. --spec bind_dict_vars(label(), label(), dict()) -> dict(). +-spec bind_dict_vars(label(), label(), dict:dict()) -> dict:dict(). bind_dict_vars(Key, Label, RaceVarMap) -> case Key =:= Label of @@ -1751,7 +1751,7 @@ compare_vars(Var1, Var2, RaceVarMap) when is_integer(Var1), is_integer(Var2) -> compare_vars(_Var1, _Var2, _RaceVarMap) -> false. --spec compare_var_list(label_type(), [label_type()], dict()) -> boolean(). +-spec compare_var_list(label_type(), [label_type()], dict:dict()) -> boolean(). compare_var_list(Var, VarList, RaceVarMap) -> lists:any(fun (V) -> compare_vars(Var, V, RaceVarMap) end, VarList). @@ -1956,7 +1956,8 @@ mnesia_tuple_argtypes(TupleStr) -> [TupleStr2|_T] = string:tokens(TupleStr1, " ,"), lists:flatten(string:tokens(TupleStr2, " |")). --spec race_var_map(var_to_map1(), var_to_map2(), dict(), op()) -> dict(). +-spec race_var_map(var_to_map1(), var_to_map2(), dict:dict(), op()) -> + dict:dict(). race_var_map(Vars1, Vars2, RaceVarMap, Op) -> case Vars1 =:= ?no_arg orelse Vars1 =:= ?bypassed diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index f0488b5ee3..ef9b00e203 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -72,7 +72,7 @@ -record(st, {callgraph :: dialyzer_callgraph:callgraph(), codeserver :: dialyzer_codeserver:codeserver(), - no_warn_unused :: set(), + no_warn_unused :: sets:set(mfa()), parent = none :: parent(), timing_server :: dialyzer_timing:timing_server(), solvers :: [solver()], @@ -137,7 +137,7 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph, -type doc_plt() :: 'undefined' | dialyzer_plt:plt(). -spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(), - doc_plt(), dialyzer_codeserver:codeserver(), set(), + doc_plt(), dialyzer_codeserver:codeserver(), sets:set(mfa()), dialyzer_timing:timing_server(), [solver()], pid()) -> {[dial_warning()], dialyzer_plt:plt(), doc_plt()}. diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 70e14781f7..31ceaf5ac5 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -83,7 +83,7 @@ list :: [constr()], deps :: [dep()], masks :: [{dep(),[non_neg_integer()]}] | - {'d',dict()}, + {'d',dict:dict(dep(), [non_neg_integer()])}, id :: {'list', dep()}}). -type constraint_list() :: #constraint_list{}. @@ -94,25 +94,30 @@ -type constr() :: constraint() | constraint_list() | constraint_ref(). --type typesig_scc() :: [{mfa(), {cerl:c_var(), cerl:c_fun()}, dict()}]. +-type types() :: erl_types:type_table(). + +-type typesig_scc() :: [{mfa(), {cerl:c_var(), cerl:c_fun()}, types()}]. -type typesig_funmap() :: [{type_var(), type_var()}]. %% Orddict --type dict_or_ets() :: {'d', dict()} | {'e', ets:tid()}. +-type prop_types() :: dict:dict(label(), types()). + +-type dict_or_ets() :: {'d', prop_types()} | {'e', ets:tid()}. -record(state, {callgraph :: dialyzer_callgraph:callgraph(), cs = [] :: [constr()], cmap = {'d', dict:new()} :: dict_or_ets(), fun_map = [] :: typesig_funmap(), - fun_arities = dict:new() :: dict(), + fun_arities = dict:new() :: dict:dict(type_var(), arity()), in_match = false :: boolean(), in_guard = false :: boolean(), module :: module(), - name_map = dict:new() :: dict(), + name_map = dict:new() :: dict:dict(mfa(), + cerl:c_fun()), next_label = 0 :: label(), self_rec :: 'false' | erl_types:erl_type(), plt :: dialyzer_plt:plt(), prop_types = {'d', dict:new()} :: dict_or_ets(), - records = dict:new() :: dict(), + records = dict:new() :: types(), scc = [] :: [type_var()], mfas :: [tuple()], solvers = [] :: [solver()] @@ -167,7 +172,7 @@ -spec analyze_scc(typesig_scc(), label(), dialyzer_callgraph:callgraph(), - dialyzer_plt:plt(), dict(), [solver()]) -> dict(). + dialyzer_plt:plt(), prop_types(), [solver()]) -> prop_types(). analyze_scc(SCC, NextLabel, CallGraph, Plt, PropTypes, Solvers0) -> Solvers = solvers(Solvers0), @@ -1890,7 +1895,7 @@ sane_maps(Map1, Map2, Keys, _S1, _S2) -> %% Solver v2 --record(v2_state, {constr_data = dict:new() :: dict(), +-record(v2_state, {constr_data = dict:new() :: dict:dict(), state :: #state{}}). v2_solve_ref(Fun, Map, State) -> diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index a4c4d37a0f..95a138dd73 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2013. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -164,14 +164,14 @@ get_core_from_abstract_code(AbstrCode, Opts) -> %% ============================================================================ -spec get_record_and_type_info(abstract_code()) -> - {'ok', dict()} | {'error', string()}. + {'ok', dict:dict()} | {'error', string()}. get_record_and_type_info(AbstractCode) -> Module = get_module(AbstractCode), get_record_and_type_info(AbstractCode, Module, dict:new()). --spec get_record_and_type_info(abstract_code(), module(), dict()) -> - {'ok', dict()} | {'error', string()}. +-spec get_record_and_type_info(abstract_code(), module(), dict:dict()) -> + {'ok', dict:dict()} | {'error', string()}. get_record_and_type_info(AbstractCode, Module, RecDict) -> get_record_and_type_info(AbstractCode, Module, [], RecDict). @@ -304,7 +304,7 @@ process_record_remote_types(CServer) -> CServer1 = dialyzer_codeserver:finalize_records(NewRecords, CServer), dialyzer_codeserver:finalize_exported_types(TempExpTypes, CServer1). --spec merge_records(dict(), dict()) -> dict(). +-spec merge_records(dict:dict(), dict:dict()) -> dict:dict(). merge_records(NewRecords, OldRecords) -> dict:merge(fun(_Key, NewVal, _OldVal) -> NewVal end, NewRecords, OldRecords). @@ -315,10 +315,10 @@ merge_records(NewRecords, OldRecords) -> %% %% ============================================================================ --type spec_dict() :: dict(). --type callback_dict() :: dict(). +-type spec_dict() :: dict:dict(). +-type callback_dict() :: dict:dict(). --spec get_spec_info(atom(), abstract_code(), dict()) -> +-spec get_spec_info(atom(), abstract_code(), dict:dict()) -> {'ok', spec_dict(), callback_dict()} | {'error', string()}. get_spec_info(ModName, AbstractCode, RecordsDict) -> @@ -383,7 +383,7 @@ get_spec_info([], SpecDict, CallbackDict, _RecordsDict, _ModName, _File) -> %% %% ============================================================================ --spec sets_filter([module()], set()) -> set(). +-spec sets_filter([module()], sets:set()) -> sets:set(). sets_filter([], ExpTypes) -> ExpTypes; @@ -434,7 +434,7 @@ format_errors([]) -> format_sig(Type) -> format_sig(Type, dict:new()). --spec format_sig(erl_types:erl_type(), dict()) -> string(). +-spec format_sig(erl_types:erl_type(), dict:dict()) -> string(). format_sig(Type, RecDict) -> "fun(" ++ Sig = lists:flatten(erl_types:t_to_string(Type, RecDict)), diff --git a/lib/dialyzer/test/file_utils.erl b/lib/dialyzer/test/file_utils.erl index 36b368760c..e1314ec8de 100644 --- a/lib/dialyzer/test/file_utils.erl +++ b/lib/dialyzer/test/file_utils.erl @@ -106,7 +106,7 @@ lcs_fast(S1, S2) -> -spec lcs_fast([string()], [string()], pos_integer(), pos_integer(), - non_neg_integer(), array()) -> {[string()], array()}. + non_neg_integer(), array:array()) -> {[string()], array:array()}. lcs_fast([], _, _, _, _, Acc) -> {[], Acc}; diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/array b/lib/dialyzer/test/opaque_SUITE_data/results/array index b05d088a03..9921b61669 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/array +++ b/lib/dialyzer/test/opaque_SUITE_data/results/array @@ -1,3 +1,3 @@ -array_use.erl:12: The type test is_tuple(array()) breaks the opaqueness of the term array() -array_use.erl:9: The attempt to match a term of type array() against the pattern {'array', _, _, 'undefined', _} breaks the opaqueness of the term +array_use.erl:12: The type test is_tuple(array:array(_)) breaks the opaqueness of the term array:array(_) +array_use.erl:9: The attempt to match a term of type array:array(_) against the pattern {'array', _, _, 'undefined', _} breaks the opaqueness of the term diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/dict b/lib/dialyzer/test/opaque_SUITE_data/results/dict index 5c6bf6a927..42f6663191 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/dict +++ b/lib/dialyzer/test/opaque_SUITE_data/results/dict @@ -1,15 +1,15 @@ -dict_use.erl:41: The attempt to match a term of type dict() against the pattern 'gazonk' breaks the opaqueness of the term -dict_use.erl:45: The attempt to match a term of type dict() against the pattern [] breaks the opaqueness of the term -dict_use.erl:46: The attempt to match a term of type dict() against the pattern 42 breaks the opaqueness of the term -dict_use.erl:51: The attempt to match a term of type dict() against the pattern [] breaks the opaqueness of the term -dict_use.erl:52: The attempt to match a term of type dict() against the pattern 42 breaks the opaqueness of the term -dict_use.erl:58: Attempt to test for equality between a term of type maybe_improper_list() and a term of opaque type dict() -dict_use.erl:60: Attempt to test for inequality between a term of type atom() and a term of opaque type dict() -dict_use.erl:64: Guard test length(D::dict()) breaks the opaqueness of its argument -dict_use.erl:65: Guard test is_atom(D::dict()) breaks the opaqueness of its argument -dict_use.erl:66: Guard test is_list(D::dict()) breaks the opaqueness of its argument -dict_use.erl:70: The type test is_list(dict()) breaks the opaqueness of the term dict() -dict_use.erl:73: The call dict:fetch('foo',[1 | 2 | 3,...]) does not have an opaque term of type dict() as 2nd argument +dict_use.erl:41: The attempt to match a term of type dict:dict(_,_) against the pattern 'gazonk' breaks the opaqueness of the term +dict_use.erl:45: The attempt to match a term of type dict:dict(_,_) against the pattern [] breaks the opaqueness of the term +dict_use.erl:46: The attempt to match a term of type dict:dict(_,_) against the pattern 42 breaks the opaqueness of the term +dict_use.erl:51: The attempt to match a term of type dict:dict(_,_) against the pattern [] breaks the opaqueness of the term +dict_use.erl:52: The attempt to match a term of type dict:dict(_,_) against the pattern 42 breaks the opaqueness of the term +dict_use.erl:58: Attempt to test for equality between a term of type maybe_improper_list() and a term of opaque type dict:dict(_,_) +dict_use.erl:60: Attempt to test for inequality between a term of type atom() and a term of opaque type dict:dict(_,_) +dict_use.erl:64: Guard test length(D::dict:dict(_,_)) breaks the opaqueness of its argument +dict_use.erl:65: Guard test is_atom(D::dict:dict(_,_)) breaks the opaqueness of its argument +dict_use.erl:66: Guard test is_list(D::dict:dict(_,_)) breaks the opaqueness of its argument +dict_use.erl:70: The type test is_list(dict:dict(_,_)) breaks the opaqueness of the term dict:dict(_,_) +dict_use.erl:73: The call dict:fetch('foo',[1 | 2 | 3,...]) does not have an opaque term of type dict:dict(_,_) as 2nd argument dict_use.erl:76: The call dict:merge(Fun::any(),42,[1 | 2,...]) does not have opaque terms as 2nd and 3rd arguments -dict_use.erl:79: The call dict:store(42,'elli',{'dict',0,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}) does not have an opaque term of type dict() as 3rd argument +dict_use.erl:79: The call dict:store(42,'elli',{'dict',0,16,16,8,80,48,{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},{{[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}}}) does not have an opaque term of type dict:dict(_,_) as 3rd argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ets b/lib/dialyzer/test/opaque_SUITE_data/results/ets index e79696bc30..e11c7a8352 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/ets +++ b/lib/dialyzer/test/opaque_SUITE_data/results/ets @@ -1,4 +1,4 @@ -ets_use.erl:12: Guard test is_integer(T::atom() | tid()) breaks the opaqueness of its argument -ets_use.erl:20: The type test is_integer(atom() | tid()) breaks the opaqueness of the term atom() | tid() -ets_use.erl:7: Guard test is_integer(T::tid()) breaks the opaqueness of its argument +ets_use.erl:12: Guard test is_integer(T::atom() | ets:tid()) breaks the opaqueness of its argument +ets_use.erl:20: The type test is_integer(atom() | ets:tid()) breaks the opaqueness of the term atom() | ets:tid() +ets_use.erl:7: Guard test is_integer(T::ets:tid()) breaks the opaqueness of its argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ewgi b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi index 5bc6b87fbb..209f27b2f2 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/ewgi +++ b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi @@ -1,4 +1,4 @@ -ewgi_api.erl:55: The call gb_trees:to_list({non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument -ewgi_testapp.erl:35: The call ewgi_testapp:htmlise_data("request_data",{non_neg_integer(),'nil' | {_,_,_,_}}) does not have a term of type [{_,_}] | gb_tree() (with opaque subterms) as 2nd argument -ewgi_testapp.erl:43: The call gb_trees:to_list(T::{non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument +ewgi_api.erl:55: The call gb_trees:to_list({non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_trees:tree(_,_) as 1st argument +ewgi_testapp.erl:35: The call ewgi_testapp:htmlise_data("request_data",{non_neg_integer(),'nil' | {_,_,_,_}}) does not have a term of type [{_,_}] | gb_trees:tree(_,_) (with opaque subterms) as 2nd argument +ewgi_testapp.erl:43: The call gb_trees:to_list(T::{non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_trees:tree(_,_) as 1st argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 index 4fe5fcfe2d..ac5ef14041 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 +++ b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop1 @@ -2,4 +2,4 @@ inf_loop1.erl:119: The pattern [{_, LNorms}] can never match the type [] inf_loop1.erl:121: The pattern [{LinksA, LNormA}, {LinksB, LNormB}] can never match the type [] inf_loop1.erl:129: The pattern [{_, Norm} | _] can never match the type [] -inf_loop1.erl:71: The call gb_trees:get(Edge::any(),Etab::array()) does not have an opaque term of type gb_tree() as 2nd argument +inf_loop1.erl:71: The call gb_trees:get(Edge::any(),Etab::array:array(_)) does not have an opaque term of type gb_trees:tree(_,_) as 2nd argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 index 4f0b79eb35..8cd2abe8cd 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 +++ b/lib/dialyzer/test/opaque_SUITE_data/results/inf_loop2 @@ -2,4 +2,4 @@ inf_loop2.erl:122: The pattern [{_, LNorms}] can never match the type [] inf_loop2.erl:124: The pattern [{LinksA, LNormA}, {LinksB, LNormB}] can never match the type [] inf_loop2.erl:132: The pattern [{_, Norm} | _] can never match the type [] -inf_loop2.erl:74: The call gb_trees:get(Edge::any(),Etab::array()) does not have an opaque term of type gb_tree() as 2nd argument +inf_loop2.erl:74: The call gb_trees:get(Edge::any(),Etab::array:array(_)) does not have an opaque term of type gb_trees:tree(_,_) as 2nd argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/para b/lib/dialyzer/test/opaque_SUITE_data/results/para new file mode 100644 index 0000000000..3aaa238de6 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/results/para @@ -0,0 +1,21 @@ + +para1.erl:18: The test para1:t(atom()) =:= para1:t(integer()) can never evaluate to 'true' +para1.erl:23: The test para1:t(atom()) =:= para1:t() can never evaluate to 'true' +para1.erl:28: The test para1:t() =:= para1:t(integer()) can never evaluate to 'true' +para1.erl:33: The test {3,2} =:= {'a','b'} can never evaluate to 'true' +para1.erl:38: Attempt to test for equality between a term of type para1_adt:t(integer()) and a term of opaque type para1_adt:t(atom()) +para1.erl:43: Attempt to test for equality between a term of type para1_adt:t() and a term of opaque type para1_adt:t(atom()) +para1.erl:48: Attempt to test for equality between a term of type para1_adt:t(integer()) and a term of opaque type para1_adt:t() +para1.erl:53: The test {3,2} =:= {'a','b'} can never evaluate to 'true' +para2.erl:103: Attempt to test for equality between a term of type para2_adt:circ({{integer(),integer()},{integer(),integer()}},{{integer(),integer()},{integer(),integer()}}) and a term of opaque type para2_adt:circ({{integer(),integer()},{integer(),integer()}}) +para2.erl:117: Attempt to test for equality between a term of type para2_adt:un(atom(),integer()) and a term of opaque type para2_adt:un(integer(),atom()) +para2.erl:31: The test 'a' =:= 'b' can never evaluate to 'true' +para2.erl:61: Attempt to test for equality between a term of type para2_adt:c2() and a term of opaque type para2_adt:c1() +para2.erl:66: The test 'a' =:= 'b' can never evaluate to 'true' +para2.erl:88: The test para2:circ({{integer(),integer()},{integer(),integer()}}) =:= para2:circ({{integer(),integer()},{integer(),integer()}},{{integer(),integer()},{integer(),integer()}}) can never evaluate to 'true' +para3.erl:28: Invalid type specification for function para3:ot2/0. The success typing is () -> 'foo' +para3.erl:36: The pattern {{{17}}} can never match the type {{{{{{_,_,_,_,_}}}}}} +para3.erl:55: Invalid type specification for function para3:t2/0. The success typing is () -> 'foo' +para3.erl:65: The attempt to match a term of type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} against the pattern {{{{{17}}}}} breaks the opaqueness of para3_adt:ot1(_,_,_,_,_) +para3.erl:68: The pattern {{{{17}}}} can never match the type {{{{{para3_adt:ot1(_,_,_,_,_)}}}}} +para3.erl:74: Invalid type specification for function para3:exp_adt/0. The success typing is () -> 3 diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/queue b/lib/dialyzer/test/opaque_SUITE_data/results/queue index 59ce33f098..5b3813c418 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/queue +++ b/lib/dialyzer/test/opaque_SUITE_data/results/queue @@ -1,11 +1,11 @@ -queue_use.erl:18: The call queue:is_empty({[],[]}) does not have an opaque term of type queue() as 1st argument -queue_use.erl:22: The call queue:in(42,Q0::{[],[]}) does not have an opaque term of type queue() as 2nd argument -queue_use.erl:27: The attempt to match a term of type queue() against the pattern {"*", Q2} breaks the opaqueness of the term -queue_use.erl:33: Attempt to test for equality between a term of type {[42,...],[]} and a term of opaque type queue() -queue_use.erl:36: The attempt to match a term of type queue() against the pattern {F, _R} breaks the opaqueness of the term -queue_use.erl:40: The call queue:out({[42,...],[]}) does not have an opaque term of type queue() as 1st argument -queue_use.erl:51: The call queue_use:is_in_queue(E::42,DB::#db{p::[],q::queue()}) contains an opaque term as 2nd argument when terms of different types are expected in these positions -queue_use.erl:56: The attempt to match a term of type #db{p::[],q::queue()} against the pattern {'db', _, {L1, L2}} breaks the opaqueness of queue() -queue_use.erl:62: The call queue_use:tuple_queue({42,'gazonk'}) does not have a term of type {_,queue()} (with opaque subterms) as 1st argument -queue_use.erl:65: The call queue:in(F::42,Q::'gazonk') does not have an opaque term of type queue() as 2nd argument +queue_use.erl:18: The call queue:is_empty({[],[]}) does not have an opaque term of type queue:queue(_) as 1st argument +queue_use.erl:22: The call queue:in(42,Q0::{[],[]}) does not have an opaque term of type queue:queue(_) as 2nd argument +queue_use.erl:27: The attempt to match a term of type queue:queue(_) against the pattern {"*", Q2} breaks the opaqueness of the term +queue_use.erl:33: Attempt to test for equality between a term of type {[42,...],[]} and a term of opaque type queue:queue(_) +queue_use.erl:36: The attempt to match a term of type queue:queue(_) against the pattern {F, _R} breaks the opaqueness of the term +queue_use.erl:40: The call queue:out({[42,...],[]}) does not have an opaque term of type queue:queue(_) as 1st argument +queue_use.erl:51: The call queue_use:is_in_queue(E::42,DB::#db{p::[],q::queue:queue(_)}) contains an opaque term as 2nd argument when terms of different types are expected in these positions +queue_use.erl:56: The attempt to match a term of type #db{p::[],q::queue:queue(_)} against the pattern {'db', _, {L1, L2}} breaks the opaqueness of queue:queue(_) +queue_use.erl:62: The call queue_use:tuple_queue({42,'gazonk'}) does not have a term of type {_,queue:queue(_)} (with opaque subterms) as 1st argument +queue_use.erl:65: The call queue:in(F::42,Q::'gazonk') does not have an opaque term of type queue:queue(_) as 2nd argument diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/simple b/lib/dialyzer/test/opaque_SUITE_data/results/simple index f55b384cbe..072ac9be8f 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/simple +++ b/lib/dialyzer/test/opaque_SUITE_data/results/simple @@ -1,6 +1,6 @@ -exact_api.erl:17: The call exact_api:set_type(A::#digraph{vtab::'notable',etab::'notable',ntab::'notable',cyclic::'true'}) does not have an opaque term of type digraph() as 1st argument -exact_api.erl:23: The call digraph:delete(G::#digraph{vtab::'notable',etab::'notable',ntab::'notable',cyclic::'true'}) does not have an opaque term of type digraph() as 1st argument +exact_api.erl:17: The call exact_api:set_type(A::#digraph{vtab::'notable',etab::'notable',ntab::'notable',cyclic::'true'}) does not have an opaque term of type digraph:graph() as 1st argument +exact_api.erl:23: The call digraph:delete(G::#digraph{vtab::'notable',etab::'notable',ntab::'notable',cyclic::'true'}) does not have an opaque term of type digraph:graph() as 1st argument exact_api.erl:55: The attempt to match a term of type exact_adt:exact_adt() against the pattern {'exact_adt'} breaks the opaqueness of the term exact_api.erl:59: The call exact_adt:exact_adt_set_type2(A::#exact_adt{}) does not have an opaque term of type exact_adt:exact_adt() as 1st argument is_rec.erl:10: The call erlang:is_record(simple1_adt:d1(),'r',2) contains an opaque term as 1st argument when terms of different types are expected in these positions @@ -73,7 +73,7 @@ simple1_api.erl:536: Guard test A::simple1_adt:d1() == 3 contains an opaque term simple1_api.erl:538: Guard test A::simple1_adt:d1() =:= 3 contains an opaque term as 1st argument simple1_api.erl:548: The call erlang:'<'(A::simple1_adt:d1(),3) contains an opaque term as 1st argument when terms of different types are expected in these positions simple1_api.erl:558: The call erlang:'=<'(A::simple1_adt:d1(),B::simple1_adt:d2()) contains an opaque term as 1st argument when terms of different types are expected in these positions -simple1_api.erl:565: Guard test {digraph(),3} > {digraph(),atom() | tid()} contains an opaque term as 2nd argument +simple1_api.erl:565: Guard test {digraph:graph(),3} > {digraph:graph(),atom() | ets:tid()} contains an opaque term as 2nd argument simple1_api.erl:91: Invalid type specification for function simple1_api:tup/0. The success typing is () -> {'a','b'} simple2_api.erl:100: The call lists:flatten(A::simple1_adt:tuple1()) contains an opaque term as 1st argument when a structured term of type [any()] is expected simple2_api.erl:116: The call lists:flatten({simple1_adt:tuple1()}) will never return since it differs in the 1st argument from the success typing arguments: ([any()]) diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/wings b/lib/dialyzer/test/opaque_SUITE_data/results/wings index 0ca91ae331..511263b70a 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/results/wings +++ b/lib/dialyzer/test/opaque_SUITE_data/results/wings @@ -1,11 +1,11 @@ -wings_dissolve.erl:103: Guard test is_list(List::gb_set()) breaks the opaqueness of its argument -wings_dissolve.erl:19: Guard test is_list(Faces::gb_set()) breaks the opaqueness of its argument -wings_dissolve.erl:272: Guard test is_list(Faces::gb_set()) breaks the opaqueness of its argument -wings_dissolve.erl:31: The call gb_sets:is_empty(Faces::[any(),...]) does not have an opaque term of type gb_set() as 1st argument +wings_dissolve.erl:103: Guard test is_list(List::gb_sets:set(_)) breaks the opaqueness of its argument +wings_dissolve.erl:19: Guard test is_list(Faces::gb_sets:set(_)) breaks the opaqueness of its argument +wings_dissolve.erl:272: Guard test is_list(Faces::gb_sets:set(_)) breaks the opaqueness of its argument +wings_dissolve.erl:31: The call gb_sets:is_empty(Faces::[any(),...]) does not have an opaque term of type gb_sets:set(_) as 1st argument wings_edge.erl:205: The pattern can never match the type <_,'soft',_> -wings_edge_cmd.erl:30: The call gb_trees:size(P::gb_set()) does not have an opaque term of type gb_tree() as 1st argument +wings_edge_cmd.erl:30: The call gb_trees:size(P::gb_sets:set(_)) does not have an opaque term of type gb_trees:tree(_,_) as 1st argument wings_edge_cmd.erl:32: The pattern [_ | Parts] can never match the type [] wings_edge_cmd.erl:32: The pattern [{_, P} | _] can never match the type [] -wings_io.erl:30: The attempt to match a term of type {'empty',queue()} against the pattern {'empty', {In, Out}} breaks the opaqueness of queue() -wings_we.erl:155: The call wings_util:gb_trees_largest_key(Etab::gb_tree()) contains an opaque term as 1st argument when a structured term of type {_,{_,_,_,'nil' | {_,_,_,'nil' | {_,_,_,_}}}} is expected +wings_io.erl:30: The attempt to match a term of type {'empty',queue:queue(_)} against the pattern {'empty', {In, Out}} breaks the opaqueness of queue:queue(_) +wings_we.erl:155: The call wings_util:gb_trees_largest_key(Etab::gb_trees:tree(_,_)) contains an opaque term as 1st argument when a structured term of type {_,{_,_,_,'nil' | {_,_,_,'nil' | {_,_,_,_}}}} is expected diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl index 8a2cd86f43..a4cec065ab 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/dict/dict_use.erl @@ -24,7 +24,7 @@ ok3() -> ok4() -> dict:fetch(foo, dict:new()). -ok5() -> % this is OK since some_mod:new/0 might be returning a dict() +ok5() -> % this is OK since some_mod:new/0 might be returning a dict:dict() dict:fetch(foo, some_mod:new()). ok6() -> diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl index 4eb202f16a..593d9a669d 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ets/ets_use.erl @@ -17,6 +17,6 @@ t3() -> is_atom(n()). % no warning since atom() is possible t4() -> - is_integer(n()). % opaque warning since tid() is opaque + is_integer(n()). % opaque warning since ets:tid() is opaque -n() -> ets:new(n, [named_table]). % -> atom() | tid() +n() -> ets:new(n, [named_table]). % -> atom() | ets:tid() diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl index 0b98f550f1..5cbc79f948 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl @@ -28,7 +28,7 @@ %% @type bag() = gb_tree() -ifdef(HAS_GB_TREE_SPEC). --type bag() :: gb_tree(). +-type bag() :: gb_trees:tree(). -else. -type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}. -endif. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl index 5da8ff0ecf..d8e15cb081 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl @@ -29,7 +29,7 @@ %% @type bag() = gb_tree() -ifdef(HAS_GB_TREE_SPEC). --type bag() :: gb_tree(). +-type bag() :: gb_trees:tree(). -else. -type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}. -endif. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl b/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl index 008b0a486a..7c34b01c2d 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/gb_sets/gb_sets_rec.erl @@ -12,12 +12,12 @@ -export([new/0, get_g/1]). --record(rec, {g :: gb_set()}). +-record(rec, {g :: gb_sets:set()}). -spec new() -> #rec{}. new() -> #rec{g = gb_sets:empty()}. --spec get_g(#rec{}) -> gb_set(). +-spec get_g(#rec{}) -> gb_sets:set(). get_g(R) -> R#rec.g. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl index 0dff16cf14..3275736e75 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop1.erl @@ -1,7 +1,7 @@ %% -*- erlang-indent-level: 2 -*- %%---------------------------------------------------------------------------- %% Non-sensical (i.e., stripped-down) program that sends the analysis -%% into an infinite loop. The #we.es field was originally a gb_tree() +%% into an infinite loop. The #we.es field was originally a gb_trees:tree() %% but the programmer declared it as an array in order to change it to %% that data type instead. In the file, there are two calls to function %% gb_trees:get/2 which seem to be the ones responsible for sending the @@ -14,7 +14,7 @@ -export([command/1]). -record(we, {id, - es = array:new() :: array(), + es = array:new() :: array:array(), vp, mirror = none}). -record(edge, {vs,ve,a = none,b = none,lf,rf,ltpr,ltsu,rtpr,rtsu}). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop2.erl b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop2.erl index 659ccaf015..3787fc6750 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop2.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/inf_loop2.erl @@ -4,7 +4,7 @@ %% restored. %% Non-sensical (i.e., stripped-down) program that sends the analysis -%% into an infinite loop. The #we.es field was originally a gb_tree() +%% into an infinite loop. The #we.es field was originally a gb_trees:tree() %% but the programmer declared it as an array in order to change it to %% that data type instead. In the file, there are two calls to function %% gb_trees:get/2 which seem to be the ones responsible for sending the @@ -17,7 +17,7 @@ -export([command/1]). -record(we, {id, - es = array:new() :: array(), + es = array:new() :: array:array(), vp, mirror = none}). -record(edge, {vs,ve,a = none,b = none,lf,rf,ltpr,ltsu,rtpr,rtsu}). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl index 9e695cec1d..e9f7ad825b 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl @@ -2,7 +2,7 @@ -export([weird/1]). --spec weird(dict() | gb_tree()) -> 42. +-spec weird(dict:dict() | gb_trees:tree()) -> 42. weird(gazonk) -> 42. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para1.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para1.erl new file mode 100644 index 0000000000..68e2c60368 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para1.erl @@ -0,0 +1,93 @@ +-module(para1). + +-compile(export_all). + +%% Parameterized opaque types + +-export_type([t/0, t/1]). + +-opaque t() :: {integer(), integer()}. + +-opaque t(A) :: {A, A}. + +-type y(A) :: {A, A}. + +tt1() -> + I = t1(), + A = t2(), + A =:= I. % never 'true' + +tt2() -> + I = t0(), + A = t2(), + A =:= I. % never 'true' + +tt3() -> + I1 = t0(), + I2 = t1(), + I1 =:= I2. % never true + +tt4() -> + I1 = y1(), + I2 = y2(), + I1 =:= I2. % cannot evaluate to true + +adt_tt1() -> + I = adt_t1(), + A = adt_t2(), + A =:= I. % opaque attempt + +adt_tt2() -> + I = adt_t0(), + A = adt_t2(), + A =:= I. % opaque attempt + +adt_tt3() -> + I1 = adt_t0(), + I2 = adt_t1(), + I1 =:= I2. % opaque attempt + +adt_tt4() -> + I1 = adt_y1(), + I2 = adt_y2(), + I1 =:= I2. % cannot evaluate to true + +-spec t0() -> t(). + +t0() -> + {3, 2}. + +-spec t1() -> t(integer()). + +t1() -> + {3, 3}. + +-spec t2() -> t(atom()). + +t2() -> + {a, b}. + +-spec y1() -> y(integer()). + +y1() -> + {3, 2}. + +-spec y2() -> y(atom()). + +y2() -> + {a, b}. + +adt_t0() -> + para1_adt:t0(). + +adt_t1() -> + para1_adt:t1(). + +adt_t2() -> + para1_adt:t2(). + +adt_y1() -> + para1_adt:y1(). + +adt_y2() -> + para1_adt:y2(). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para1_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para1_adt.erl new file mode 100644 index 0000000000..95ac6b7982 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para1_adt.erl @@ -0,0 +1,36 @@ +-module(para1_adt). + +-export([t0/0, t1/0, t2/0, y1/0, y2/0]). + +-export_type([t/0, t/1, y/1]). + +-opaque t() :: {integer(), integer()}. + +-opaque t(A) :: {A, A}. + +-type y(A) :: {A, A}. + +-spec t0() -> t(). + +t0() -> + {3, 2}. + +-spec t1() -> t(integer()). + +t1() -> + {3, 3}. + +-spec t2() -> t(atom()). + +t2() -> + {a, b}. + +-spec y1() -> y(integer()). + +y1() -> + {3, 2}. + +-spec y2() -> y(atom()). + +y2() -> + {a, b}. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para2.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para2.erl new file mode 100644 index 0000000000..09b2235fa5 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para2.erl @@ -0,0 +1,123 @@ +-module(para2). + +-compile(export_all). + +%% More parameterized opaque types + +-export_type([strange/1]). + +-export_type([c1/0, c2/0]). + +-export_type([circ/1, circ/2]). + +-opaque strange(A) :: {B, B, A}. + +-spec t(strange(integer())) -> strange(atom()). + +t({3, 4, 5}) -> + {a, b, c}. + +-opaque c1() :: c2(). +-opaque c2() :: c1(). + +c() -> + A = c1(), + B = c2(), + A =:= B. + +t() -> + A = ct1(), + B = ct2(), + A =:= B. % can never evaluate to 'true' + +-spec c1() -> c1(). + +c1() -> + a. + +-spec c2() -> c2(). + +c2() -> + a. + +-type ct1() :: ct2(). +-type ct2() :: ct1(). + +-spec ct1() -> ct1(). + +ct1() -> + a. + +-spec ct2() -> ct2(). + +ct2() -> + b. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +c_adt() -> + A = c1_adt(), + B = c2_adt(), + A =:= B. % opaque attempt + +t_adt() -> + A = ct1_adt(), + B = ct2_adt(), + A =:= B. % can never evaluate to true + +c1_adt() -> + para2_adt:c1(). + +c2_adt() -> + para2_adt:c2(). + +ct1_adt() -> + para2_adt:ct1(). + +ct2_adt() -> + para2_adt:ct2(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-opaque circ(A) :: circ(A, A). +-opaque circ(A, B) :: circ({A, B}). + +tcirc() -> + A = circ1(), + B = circ2(), + A =:= B. % can never evaluate to 'true' (but the types are not OK, or?) + +-spec circ1() -> circ(integer()). + +circ1() -> + 3. + +-spec circ2() -> circ(integer(), integer()). + +circ2() -> + {3, 3}. + +tcirc_adt() -> + A = circ1_adt(), + B = circ2_adt(), + A =:= B. % opaque attempt (one would expect them to be the same...) + +circ1_adt() -> + para2_adt:circ1(). + +circ2_adt() -> + para2_adt:circ2(). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +u_adt() -> + A = u1_adt(), + B = u2_adt(), + %% The resulting types are equal, but not the parameters: + A =:= B. % opaque attempt + +u1_adt() -> + para2_adt:u1(). + +u2_adt() -> + para2_adt:u2(). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para2_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para2_adt.erl new file mode 100644 index 0000000000..96df437c67 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para2_adt.erl @@ -0,0 +1,64 @@ +-module(para2_adt). + +%% More parameterized opaque types + +-export_type([c1/0, c2/0]). + +-export_type([ct1/0, ct2/0]). + +-export_type([circ/1, circ/2]). + +-export_type([un/2]). + +-export([c1/0, c2/0, ct1/0, ct2/0, circ1/0, circ2/0, u1/0, u2/0]). + +-opaque c1() :: c2(). +-opaque c2() :: c1(). + +-spec c1() -> c1(). + +c1() -> + a. + +-spec c2() -> c2(). + +c2() -> + a. + +-type ct1() :: ct2(). +-type ct2() :: ct1(). + +-spec ct1() -> ct1(). + +ct1() -> + a. + +-spec ct2() -> ct2(). + +ct2() -> + b. + +-opaque circ(A) :: circ(A, A). +-opaque circ(A, B) :: circ({A, B}). + +-spec circ1() -> circ(integer()). + +circ1() -> + 3. + +-spec circ2() -> circ(integer(), integer()). + +circ2() -> + {3, 3}. + +-opaque un(A, B) :: A | B. + +-spec u1() -> un(integer(), atom()). + +u1() -> + 3. + +-spec u2() -> un(atom(), integer()). + +u2() -> + 3. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para3.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para3.erl new file mode 100644 index 0000000000..792ae40d39 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para3.erl @@ -0,0 +1,77 @@ +-module(para3). + +-export([t/0, t1/1, t2/0, ot1/1, ot2/0, t1_adt/0, t2_adt/0]). + +-export([exp_adt/0]). + +%% More opaque tests. + +-export_type([ot1/0, ot1/1, ot1/2, ot1/3, ot1/4, ot1/5]). + +-opaque ot1() :: {ot1(_)}. + +-opaque ot1(A) :: {ot1(A, A)}. + +-opaque ot1(A, B) :: {ot1(A, B, A)}. + +-opaque ot1(A, B, C) :: {ot1(A, B, C, A)}. + +-opaque ot1(A, B, C, D) :: {ot1(A, B, C, D, A)}. + +-opaque ot1(A, B, C, D, E) :: {A, B, C, D, E}. + +-spec ot1(_) -> ot1(). + +ot1(A) -> + {{{{{A, A, A, A, A}}}}}. + +-spec ot2() -> ot1(). % invalid type spec + +ot2() -> + foo. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +t() -> + {{{17}}} = t1(3). %% pattern can never match + +-type t1() :: {t1(_)}. + +-type t1(A) :: {t1(A, A)}. + +-type t1(A, B) :: {t1(A, B, A)}. + +-type t1(A, B, C) :: {t1(A, B, C, A)}. + +-type t1(A, B, C, D) :: {t1(A, B, C, D, A)}. + +-type t1(A, B, C, D, E) :: {A, B, C, D, E}. + +-spec t1(_) -> t1(). + +t1(A) -> + {{{{{A, A, A, A, A}}}}}. + +-spec t2() -> t1(). % invalid type spec + +t2() -> + foo. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Shows that the list TypeNames in t_from_form must include ArgsLen. + +t1_adt() -> + {{{{{17}}}}} = para3_adt:t1(3). % breaks the opaqueness + +t2_adt() -> + {{{{17}}}} = para3_adt:t1(3). % can never match + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-type exp() :: para3_adt:exp1(para3_adt:exp2()). + +-spec exp_adt() -> exp(). + +exp_adt() -> + 3. diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/para/para3_adt.erl b/lib/dialyzer/test/opaque_SUITE_data/src/para/para3_adt.erl new file mode 100644 index 0000000000..3919b846e6 --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/para/para3_adt.erl @@ -0,0 +1,27 @@ +-module(para3_adt). + +-export([t1/1]). + +-export_type([t1/0, t1/1, t1/2, t1/3, t1/4, ot1/5]). + +-export_type([exp1/1, exp2/0]). + +-type t1() :: {t1(_)}. + +-type t1(A) :: {t1(A, A)}. + +-type t1(A, B) :: {t1(A, B, A)}. + +-type t1(A, B, C) :: {t1(A, B, C, A)}. + +-type t1(A, B, C, D) :: {ot1(A, B, C, D, A)}. + +-opaque ot1(A, B, C, D, E) :: {A, B, C, D, E}. + +-spec t1(_) -> t1(). + +t1(A) -> + {{{{{A, A, A, A, A}}}}}. + +-opaque exp1(T) :: T. +-opaque exp2() :: integer(). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/simple/exact_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/simple/exact_api.erl index 5f7ab4f3aa..c19330eb30 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/simple/exact_api.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/simple/exact_api.erl @@ -10,14 +10,14 @@ ntab = notable :: ets:tab(), cyclic = true :: boolean()}). --spec new() -> digraph(). +-spec new() -> digraph:graph(). new() -> A = #digraph{}, set_type(A), % does not have an opaque term as 1st argument A. --spec set_type(digraph()) -> true. +-spec set_type(digraph:graph()) -> true. set_type(G) -> digraph:delete(G). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl index 8f0da1f5dc..ca6bc0ab4a 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/wings/wings_util.erl @@ -14,12 +14,12 @@ rel2fam(Rel) -> sofs:to_external(sofs:relation_to_family(sofs:relation(Rel))). -%% a definition that does not violate the opaqueness of gb_tree() +%% a definition that does not violate the opaqueness of gb_trees:tree() gb_trees_smallest_key(Tree) -> {Key, _V} = gb_trees:smallest(Tree), Key. -%% a definition that violates the opaqueness of gb_tree() +%% a definition that violates the opaqueness of gb_trees:tree() gb_trees_largest_key({_, Tree}) -> largest_key1(Tree). diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl index 38c6051c58..e094d1982b 100644 --- a/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl +++ b/lib/dialyzer/test/opaque_SUITE_data/src/zoltan_kis2.erl @@ -2,7 +2,7 @@ -export([get/2]). --opaque data() :: gb_tree(). +-opaque data() :: gb_trees:tree(). -spec get(term(), data()) -> term(). diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 index d640f564cd..0382627cfc 100644 --- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 +++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow3 @@ -1,3 +1,3 @@ -ets_insert_control_flow3.erl:21: The call ets:insert(Table::atom() | tid(),{'root',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'root') call in ets_insert_control_flow3.erl on line 12 -ets_insert_control_flow3.erl:23: The call ets:insert(Table::atom() | tid(),{'user',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'user') call in ets_insert_control_flow3.erl on line 13 +ets_insert_control_flow3.erl:21: The call ets:insert(Table::atom() | ets:tid(),{'root',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'root') call in ets_insert_control_flow3.erl on line 12 +ets_insert_control_flow3.erl:23: The call ets:insert(Table::atom() | ets:tid(),{'user',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'user') call in ets_insert_control_flow3.erl on line 13 diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 index 6f34e75902..22944fd066 100644 --- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 +++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow4 @@ -1,3 +1,3 @@ -ets_insert_control_flow4.erl:21: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow4.erl on line 12, the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow4.erl on line 13 -ets_insert_control_flow4.erl:23: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow4.erl on line 12, the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow4.erl on line 13 +ets_insert_control_flow4.erl:21: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line 12, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line 13 +ets_insert_control_flow4.erl:23: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line 12, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow4.erl on line 13 diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 index 5af592f43f..e172887f34 100644 --- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 +++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_control_flow5 @@ -1,5 +1,5 @@ -ets_insert_control_flow5.erl:22: The call ets:insert(Table::atom() | tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line 16 -ets_insert_control_flow5.erl:23: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow5.erl on line 12, the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow5.erl on line 13 -ets_insert_control_flow5.erl:25: The call ets:insert(Table::atom() | tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line 16 -ets_insert_control_flow5.erl:26: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow5.erl on line 12, the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_control_flow5.erl on line 13 +ets_insert_control_flow5.erl:22: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line 16 +ets_insert_control_flow5.erl:23: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line 12, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line 13 +ets_insert_control_flow5.erl:25: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_control_flow5.erl on line 16 +ets_insert_control_flow5.erl:26: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line 12, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_control_flow5.erl on line 13 diff --git a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param index 58f934a190..6a34337a2c 100644 --- a/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param +++ b/lib/dialyzer/test/race_SUITE_data/results/ets_insert_param @@ -1,5 +1,5 @@ -ets_insert_param.erl:13: The call ets:insert(Table::atom() | tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'welcome_msg') call in ets_insert_param.erl on line 10 -ets_insert_param.erl:14: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_param.erl on line 14, the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_param.erl on line 15 -ets_insert_param.erl:17: The call ets:insert(Table::atom() | tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'welcome_msg') call in ets_insert_param.erl on line 10 -ets_insert_param.erl:18: The call ets:insert(Table::atom() | tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | tid(),'pass') call in ets_insert_param.erl on line 18 +ets_insert_param.erl:13: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_param.erl on line 10 +ets_insert_param.erl:14: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line 14, the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line 15 +ets_insert_param.erl:17: The call ets:insert(Table::atom() | ets:tid(),{'welcome_msg',[any(),...]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'welcome_msg') call in ets_insert_param.erl on line 10 +ets_insert_param.erl:18: The call ets:insert(Table::atom() | ets:tid(),{'pass',[pos_integer()]}) might have an unintended effect due to a possible race condition caused by its combination with the ets:lookup(Table::atom() | ets:tid(),'pass') call in ets_insert_param.erl on line 18 diff --git a/lib/dialyzer/test/small_SUITE_data/results/predef b/lib/dialyzer/test/small_SUITE_data/results/predef new file mode 100644 index 0000000000..85e210d6e4 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/predef @@ -0,0 +1,8 @@ + +predef.erl:19: Invalid type specification for function predef:array/1. The success typing is (array:array(_)) -> array:array(_) +predef.erl:24: Invalid type specification for function predef:dict/1. The success typing is (dict:dict(_,_)) -> dict:dict(_,_) +predef.erl:29: Invalid type specification for function predef:digraph/1. The success typing is (digraph:graph()) -> [any()] +predef.erl:39: Invalid type specification for function predef:gb_set/1. The success typing is (gb_sets:set(_)) -> gb_sets:set(_) +predef.erl:44: Invalid type specification for function predef:gb_tree/1. The success typing is (gb_trees:tree(_,_)) -> gb_trees:tree(_,_) +predef.erl:49: Invalid type specification for function predef:queue/1. The success typing is (queue:queue(_)) -> queue:queue(_) +predef.erl:54: Invalid type specification for function predef:set/1. The success typing is (sets:set(_)) -> sets:set(_) diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_construct b/lib/dialyzer/test/small_SUITE_data/results/record_construct index c0110b144f..4c40fec298 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/record_construct +++ b/lib/dialyzer/test/small_SUITE_data/results/record_construct @@ -1,6 +1,6 @@ record_construct.erl:15: Function t_opa/0 has no local return -record_construct.erl:16: Record construction #r_opa{b::gb_set(),c::42,e::'false'} violates the declared type of field c::boolean() +record_construct.erl:16: Record construction #r_opa{b::gb_sets:set(_),c::42,e::'false'} violates the declared type of field c::boolean() record_construct.erl:20: Function t_rem/0 has no local return record_construct.erl:21: Record construction #r_rem{a::'gazonk'} violates the declared type of field a::string() record_construct.erl:6: Function t_loc/0 has no local return diff --git a/lib/dialyzer/test/small_SUITE_data/src/predef.erl b/lib/dialyzer/test/small_SUITE_data/src/predef.erl new file mode 100644 index 0000000000..c2364fd1c2 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/predef.erl @@ -0,0 +1,67 @@ +-module(predef). + +-export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1, + queue/1, set/1, tid/0, tid2/0]). + +-export_type([array/0, digraph/0, gb_set/0]). + +%% Before R17B local re-definitions of pre-defined opaque types were +%% ignored but did not generate any warning. +-opaque array() :: atom(). +-opaque digraph() :: atom(). +-opaque gb_set() :: atom(). +-type dict() :: atom(). +-type gb_tree() :: atom(). +-type queue() :: atom(). +-type set() :: atom(). +-type tid() :: atom(). + +-spec array(array()) -> array:array(). + +array(A) -> + array:relax(A). + +-spec dict(dict()) -> dict:dict(). + +dict(D) -> + dict:store(1, a, D). + +-spec digraph(digraph()) -> [digraph:edge()]. + +digraph(G) -> + digraph:edges(G). + +-spec digraph2(digraph:graph()) -> [digraph:edge()]. + +digraph2(G) -> + digraph:edges(G). + +-spec gb_set(gb_set()) -> gb_sets:set(). + +gb_set(S) -> + gb_sets:balance(S). + +-spec gb_tree(gb_tree()) -> gb_trees:tree(). + +gb_tree(S) -> + gb_trees:balance(S). + +-spec queue(queue()) -> queue:queue(). + +queue(Q) -> + queue:reverse(Q). + +-spec set(set()) -> sets:set(). + +set(S) -> + sets:union([S]). + +-spec tid() -> tid(). + +tid() -> + ets:new(tid, []). + +-spec tid2() -> ets:tid(). + +tid2() -> + ets:new(tid, []). diff --git a/lib/dialyzer/test/small_SUITE_data/src/predef2.erl b/lib/dialyzer/test/small_SUITE_data/src/predef2.erl new file mode 100644 index 0000000000..b1d941a49a --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/predef2.erl @@ -0,0 +1,56 @@ +-module(predef2). + +-export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1, + queue/1, set/1, tid/0, tid2/0]). + +-export_type([array/0, digraph/0, gb_set/0]). + +-spec array(array()) -> array:array(). + +array(A) -> + array:relax(A). + +-spec dict(dict()) -> dict:dict(). + +dict(D) -> + dict:store(1, a, D). + +-spec digraph(digraph()) -> [digraph:edge()]. + +digraph(G) -> + digraph:edges(G). + +-spec digraph2(digraph:graph()) -> [digraph:edge()]. + +digraph2(G) -> + digraph:edges(G). + +-spec gb_set(gb_set()) -> gb_sets:set(). + +gb_set(S) -> + gb_sets:balance(S). + +-spec gb_tree(gb_tree()) -> gb_trees:tree(). + +gb_tree(S) -> + gb_trees:balance(S). + +-spec queue(queue()) -> queue:queue(). + +queue(Q) -> + queue:reverse(Q). + +-spec set(set()) -> sets:set(). + +set(S) -> + sets:union([S]). + +-spec tid() -> tid(). + +tid() -> + ets:new(tid, []). + +-spec tid2() -> ets:tid(). + +tid2() -> + ets:new(tid, []). diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl b/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl index 54cc2601bd..b250c6ee65 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/record_construct.erl @@ -7,7 +7,7 @@ t_loc() -> #r_loc{}. -record(r_opa, {a :: atom(), - b = gb_sets:new() :: gb_set(), + b = gb_sets:new() :: gb_sets:set(), c = 42 :: boolean(), d, % untyped on purpose e = false :: boolean()}). diff --git a/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings b/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings index 2784f2119e..24b44c1b5c 100644 --- a/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings +++ b/lib/dialyzer/test/unmatched_returns_SUITE_data/results/lc_warnings @@ -1,5 +1,5 @@ lc_warnings.erl:32: Expression produces a value of type [opaque_atom_adt:opaque_atom()], but this value is unmatched -lc_warnings.erl:43: Expression produces a value of type [array()], but this value is unmatched +lc_warnings.erl:43: Expression produces a value of type [array:array(_)], but this value is unmatched lc_warnings.erl:65: Expression produces a value of type [lc_warnings:opaque_tuple()], but this value is unmatched lc_warnings.erl:7: Expression produces a value of type ['ok' | {'error',atom()}], but this value is unmatched diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 466c9df951..211a354c74 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -35,7 +35,7 @@ %% Exported functions %% --spec type(Form::syntaxTree(), TypeDocs::dict()) -> #tag{}. +-spec type(Form::syntaxTree(), TypeDocs::dict:dict()) -> #tag{}. %% @doc Convert an Erlang type to EDoc representation. %% TypeDocs is a dict of {Name, Doc}. @@ -88,7 +88,7 @@ dummy_spec(Form) -> -spec docs(Forms::[syntaxTree()], CommentFun :: fun( ([syntaxTree()], Line :: term()) -> #tag{} )) - -> dict(). + -> dict:dict(). %% @doc Find comments after -type/-opaque declarations. %% Postcomments "inside" the type are skipped. diff --git a/lib/eunit/src/eunit_serial.erl b/lib/eunit/src/eunit_serial.erl index 80e79116e3..1a0179a5df 100644 --- a/lib/eunit/src/eunit_serial.erl +++ b/lib/eunit/src/eunit_serial.erl @@ -56,9 +56,9 @@ %% future use, and/or cancel the current item and possibly one or more %% of its parent groups. --record(state, {listeners :: set(), - cancelled = eunit_lib:trie_new() :: gb_tree(), - messages = dict:new() :: dict()}). +-record(state, {listeners :: sets:set(), + cancelled = eunit_lib:trie_new() :: gb_trees:tree(), + messages = dict:new() :: dict:dict()}). start(Pids) -> spawn(fun () -> serializer(Pids) end). diff --git a/lib/hipe/cerl/cerl_closurean.erl b/lib/hipe/cerl/cerl_closurean.erl index 021acd5b35..1b325703ae 100644 --- a/lib/hipe/cerl/cerl_closurean.erl +++ b/lib/hipe/cerl/cerl_closurean.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -78,7 +78,8 @@ %% function; see `analyze' for details. -spec annotate(cerl:cerl()) -> - {cerl:cerl(), outlist(), dict(), escapes(), dict(), dict()}. + {cerl:cerl(), outlist(), dict:dict(), + escapes(), dict:dict(), dict:dict()}. annotate(Tree) -> {Xs, Out, Esc, Deps, Par} = analyze(Tree), @@ -206,7 +207,8 @@ append_ann(Tag, Val, []) -> %% variable labeled `escape', which will hold the set of escaped labels. %% initially it contains `top' and `external'. --spec analyze(cerl:cerl()) -> {outlist(), dict(), escapes(), dict(), dict()}. +-spec analyze(cerl:cerl()) -> + {outlist(), dict:dict(), escapes(), dict:dict(), dict:dict()}. analyze(Tree) -> %% Note that we use different name spaces for variable labels and diff --git a/lib/hipe/cerl/cerl_messagean.erl b/lib/hipe/cerl/cerl_messagean.erl index ca812a0f0d..7911b875a9 100644 --- a/lib/hipe/cerl/cerl_messagean.erl +++ b/lib/hipe/cerl/cerl_messagean.erl @@ -1,7 +1,7 @@ %% ===================================================================== %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -182,7 +182,7 @@ -type label() :: integer() | 'external' | 'top'. -type ordset(X) :: [X]. % XXX: TAKE ME OUT --spec annotate(cerl:cerl()) -> {cerl:cerl(), ordset(label()), dict()}. +-spec annotate(cerl:cerl()) -> {cerl:cerl(), ordset(label()), dict:dict()}. annotate(Tree) -> {Esc0, Vars} = analyze(Tree), diff --git a/lib/hipe/cerl/cerl_typean.erl b/lib/hipe/cerl/cerl_typean.erl index ccd8903658..f694c07c82 100644 --- a/lib/hipe/cerl/cerl_typean.erl +++ b/lib/hipe/cerl/cerl_typean.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -242,7 +242,7 @@ delete_ann(_, []) -> -type labelset() :: ordset(label()). -type outlist() :: [labelset()] | 'none'. --spec analyze(cerl:cerl()) -> {outlist(), dict(), dict()}. +-spec analyze(cerl:cerl()) -> {outlist(), dict:dict(), dict:dict()}. analyze(Tree) -> analyze(Tree, ?DEF_LIMIT). diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 329a71b099..32390045e3 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -228,7 +228,7 @@ -export([t_is_identifier/1]). -endif. --export_type([erl_type/0]). +-export_type([erl_type/0, type_table/0, var_table/0]). %%-define(DEBUG, true). @@ -363,6 +363,15 @@ -type opaques() :: [erl_type()] | 'universe'. +-type record_key() :: {'record', atom()}. +-type type_key() :: {'type' | 'opaque', atom(), arity()}. +-type record_value() :: orddict:orddict(). % XXX. To be refined +-type type_value() :: {module(), erl_type(), atom()}. +-type type_table() :: dict:dict(record_key(), record_value()) + | dict:dict(type_key(), type_value()). + +-type var_table() :: dict:dict(atom(), erl_type()). + %%----------------------------------------------------------------------------- %% Unions %% @@ -723,7 +732,7 @@ decorate_tuples_in_sets([T1|Tuples], L2, Opaques, Acc) -> decorate_tuples_in_sets([], _L, _Opaques, Acc) -> lists:reverse(Acc). --spec t_opaque_from_records(dict()) -> [erl_type()]. +-spec t_opaque_from_records(type_table()) -> [erl_type()]. t_opaque_from_records(RecDict) -> OpaqueRecDict = @@ -798,7 +807,9 @@ t_is_remote(Type) -> is_remote(?remote(_)) -> true; is_remote(_) -> false. --spec t_solve_remote(erl_type(), set(), dict()) -> erl_type(). +-type mod_records() :: dict:dict(module(), type_table()). + +-spec t_solve_remote(erl_type(), sets:set(mfa()), mod_records()) -> erl_type(). t_solve_remote(Type, ExpTypes, Records) -> {RT, _RR} = t_solve_remote(Type, ExpTypes, Records, []), @@ -1962,7 +1973,7 @@ t_timeout() -> -spec t_array() -> erl_type(). t_array() -> - t_opaque(array, array, [], + t_opaque(array, array, [t_any()], t_tuple([t_atom('array'), t_sup([t_atom('undefined'), t_non_neg_integer()]), t_sup([t_atom('undefined'), t_non_neg_integer()]), @@ -1972,7 +1983,7 @@ t_array() -> -spec t_dict() -> erl_type(). t_dict() -> - t_opaque(dict, dict, [], + t_opaque(dict, dict, [t_any(), t_any()], t_tuple([t_atom('dict'), t_sup([t_atom('undefined'), t_non_neg_integer()]), t_sup([t_atom('undefined'), t_non_neg_integer()]), @@ -2008,12 +2019,12 @@ t_gb_tree() -> -spec t_queue() -> erl_type(). t_queue() -> - t_opaque(queue, queue, [], t_tuple([t_list(), t_list()])). + t_opaque(queue, queue, [t_any()], t_tuple([t_list(), t_list()])). -spec t_set() -> erl_type(). t_set() -> - t_opaque(sets, set, [], + t_opaque(sets, set, [t_any()], t_tuple([t_atom('set'), t_non_neg_integer(), t_non_neg_integer(), t_pos_integer(), t_non_neg_integer(), t_non_neg_integer(), t_non_neg_integer(), @@ -2031,18 +2042,6 @@ all_opaque_builtins() -> [t_array(), t_dict(), t_digraph(), t_gb_set(), t_gb_tree(), t_queue(), t_set(), t_tid()]. --spec is_opaque_builtin(atom(), atom()) -> boolean(). - -is_opaque_builtin(array, array) -> true; -is_opaque_builtin(dict, dict) -> true; -is_opaque_builtin(digraph, digraph) -> true; -is_opaque_builtin(gb_sets, gb_set) -> true; -is_opaque_builtin(gb_trees, gb_tree) -> true; -is_opaque_builtin(queue, queue) -> true; -is_opaque_builtin(sets, set) -> true; -is_opaque_builtin(ets, tid) -> true; -is_opaque_builtin(_, _) -> false. - %%------------------------------------ %% ?none is allowed in products. A product of size 1 is not a product. @@ -2831,9 +2830,9 @@ comb(Mod, Name, Args, S, T) -> false -> T#opaque{struct = S} end. -is_same_name(Mod, Name, Args, - ?opaque([#opaque{mod = Mod, name = Name, args = Args}])) -> - true; +is_same_name(Mod1, Name1, Args1, + ?opaque([#opaque{mod = Mod2, name = Name2, args = Args2}])) -> + is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}); is_same_name(_, _, _, _) -> false. %% Combining two lists this way can be very time consuming... @@ -3035,13 +3034,13 @@ findfirst(N1, N2, U1, B1, U2, B2) -> %% to types. Hans Bolinder suggested the use of lists of Key-Value pairs for %% this data structure and measurements showed a non-trivial speedup when using %% them for operations within this module (e.g. in t_unify/2). However, there -%% is code outside erl_types that still passes a dict() in the 2nd argument. +%% is code outside erl_types that still passes a dict:dict() in the 2nd argument. %% So, for the time being, this module provides a t_subst/2 function for these %% external calls and a clone of it (t_subst_kv/2) which is used from all calls %% from within this module. This code duplication needs to be eliminated at %% some point. --spec t_subst(erl_type(), dict()) -> erl_type(). +-spec t_subst(erl_type(), dict:dict(atom(), erl_type())) -> erl_type(). t_subst(T, Dict) -> case t_has_var(T) of @@ -3785,7 +3784,7 @@ t_limit_k(T, _K) -> T. %% %%============================================================================ --spec t_abstract_records(erl_type(), dict()) -> erl_type(). +-spec t_abstract_records(erl_type(), type_table()) -> erl_type(). t_abstract_records(?list(Contents, Termination, Size), RecDict) -> case t_abstract_records(Contents, RecDict) of @@ -3865,7 +3864,7 @@ t_map(Fun, T) -> t_to_string(T) -> t_to_string(T, dict:new()). --spec t_to_string(erl_type(), dict()) -> string(). +-spec t_to_string(erl_type(), type_table()) -> string(). t_to_string(?any, _RecDict) -> "any()"; @@ -4051,7 +4050,7 @@ record_fields_to_string([F|Fs], [{FName, _DefType}|FDefs], RecDict, Acc) -> record_fields_to_string([], [], _RecDict, Acc) -> lists:reverse(Acc). --spec record_field_diffs_to_string(erl_type(), dict()) -> string(). +-spec record_field_diffs_to_string(erl_type(), type_table()) -> string(). record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) -> [TagAtom] = atom_vals(Tag), @@ -4086,9 +4085,9 @@ union_sequence(Types, RecDict) -> -ifdef(DEBUG). opaque_type(Mod, Name, _Args, S, RecDict) -> - ArgsString = "[ARGS:" ++ comma_sequence(_Args, RecDict) ++ "]", + ArgsString = comma_sequence(_Args, RecDict), String = t_to_string(S, RecDict), - opaque_name(Mod, Name, ArgsString ++ String). + opaque_name(Mod, Name, ArgsString) ++ "[" ++ String ++ "]". -else. opaque_type(Mod, Name, Args, _S, RecDict) -> ArgsString = comma_sequence(Args, RecDict), @@ -4100,11 +4099,16 @@ opaque_name(Mod, Name, Extra) -> flat_format("~s(~s)", [S, Extra]). mod_name(Mod, Name) -> - case is_opaque_builtin(Mod, Name) of + case is_obsolete_opaque_builtin(Mod, Name) of true -> flat_format("~w", [Name]); false -> flat_format("~w:~w", [Mod, Name]) end. +is_obsolete_opaque_builtin(digraph, digraph) -> true; +is_obsolete_opaque_builtin(gb_sets, gb_set) -> true; +is_obsolete_opaque_builtin(gb_trees, gb_tree) -> true; +is_obsolete_opaque_builtin(_, _) -> false. + %%============================================================================= %% %% Build a type from parse forms. @@ -4116,19 +4120,20 @@ mod_name(Mod, Name) -> t_from_form(Form) -> t_from_form(Form, dict:new()). --spec t_from_form(parse_form(), dict()) -> erl_type(). +-spec t_from_form(parse_form(), type_table()) -> erl_type(). t_from_form(Form, RecDict) -> t_from_form(Form, RecDict, dict:new()). --spec t_from_form(parse_form(), dict(), dict()) -> erl_type(). +-spec t_from_form(parse_form(), type_table(), var_table()) -> erl_type(). t_from_form(Form, RecDict, VarDict) -> {T, _R} = t_from_form(Form, [], RecDict, VarDict), T. --type type_names() :: [{'type' | 'opaque' | 'record', atom()}]. --spec t_from_form(parse_form(), type_names(), dict(), dict()) -> +-type type_names() :: [type_key() | record_key()]. + +-spec t_from_form(parse_form(), type_names(), type_table(), var_table()) -> {erl_type(), type_names()}. t_from_form({var, _L, '_'}, _TypeNames, _RecDict, _VarDict) -> @@ -4167,8 +4172,8 @@ t_from_form({type, _L, any, []}, _TypeNames, _RecDict, _VarDict) -> {t_any(), []}; t_from_form({type, _L, arity, []}, _TypeNames, _RecDict, _VarDict) -> {t_arity(), []}; -t_from_form({type, _L, array, []}, _TypeNames, _RecDict, _VarDict) -> - {t_array(), []}; +t_from_form({type, _L, array, []}, TypeNames, RecDict, VarDict) -> + builtin_type(array, t_array(), TypeNames, RecDict, VarDict); t_from_form({type, _L, atom, []}, _TypeNames, _RecDict, _VarDict) -> {t_atom(), []}; t_from_form({type, _L, binary, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4190,10 +4195,10 @@ t_from_form({type, _L, byte, []}, _TypeNames, _RecDict, _VarDict) -> {t_byte(), []}; t_from_form({type, _L, char, []}, _TypeNames, _RecDict, _VarDict) -> {t_char(), []}; -t_from_form({type, _L, dict, []}, _TypeNames, _RecDict, _VarDict) -> - {t_dict(), []}; -t_from_form({type, _L, digraph, []}, _TypeNames, _RecDict, _VarDict) -> - {t_digraph(), []}; +t_from_form({type, _L, dict, []}, TypeNames, RecDict, VarDict) -> + builtin_type(dict, t_dict(), TypeNames, RecDict, VarDict); +t_from_form({type, _L, digraph, []}, TypeNames, RecDict, VarDict) -> + builtin_type(digraph, t_digraph(), TypeNames, RecDict, VarDict); t_from_form({type, _L, float, []}, _TypeNames, _RecDict, _VarDict) -> {t_float(), []}; t_from_form({type, _L, function, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4209,10 +4214,10 @@ t_from_form({type, _L, 'fun', [{type, _, product, Domain}, Range]}, {L, R1} = list_from_form(Domain, TypeNames, RecDict, VarDict), {T, R2} = t_from_form(Range, TypeNames, RecDict, VarDict), {t_fun(L, T), R1 ++ R2}; -t_from_form({type, _L, gb_set, []}, _TypeNames, _RecDict, _VarDict) -> - {t_gb_set(), []}; -t_from_form({type, _L, gb_tree, []}, _TypeNames, _RecDict, _VarDict) -> - {t_gb_tree(), []}; +t_from_form({type, _L, gb_set, []}, TypeNames, RecDict, VarDict) -> + builtin_type(gb_set, t_gb_set(), TypeNames, RecDict, VarDict); +t_from_form({type, _L, gb_tree, []}, TypeNames, RecDict, VarDict) -> + builtin_type(gb_tree, t_gb_tree(), TypeNames, RecDict, VarDict); t_from_form({type, _L, identifier, []}, _TypeNames, _RecDict, _VarDict) -> {t_identifier(), []}; t_from_form({type, _L, integer, []}, _TypeNames, _RecDict, _VarDict) -> @@ -4285,8 +4290,8 @@ t_from_form({type, _L, maybe_improper_list, [Content, Termination]}, t_from_form({type, _L, product, Elements}, TypeNames, RecDict, VarDict) -> {L, R} = list_from_form(Elements, TypeNames, RecDict, VarDict), {t_product(L), R}; -t_from_form({type, _L, queue, []}, _TypeNames, _RecDict, _VarDict) -> - {t_queue(), []}; +t_from_form({type, _L, queue, []}, TypeNames, RecDict, VarDict) -> + builtin_type(queue, t_queue(), TypeNames, RecDict, VarDict); t_from_form({type, _L, range, [From, To]} = Type, _TypeNames, _RecDict, _VarDict) -> case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of @@ -4298,14 +4303,14 @@ t_from_form({type, _L, record, [Name|Fields]}, TypeNames, RecDict, VarDict) -> record_from_form(Name, Fields, TypeNames, RecDict, VarDict); t_from_form({type, _L, reference, []}, _TypeNames, _RecDict, _VarDict) -> {t_reference(), []}; -t_from_form({type, _L, set, []}, _TypeNames, _RecDict, _VarDict) -> - {t_set(), []}; +t_from_form({type, _L, set, []}, TypeNames, RecDict, VarDict) -> + builtin_type(set, t_set(), TypeNames, RecDict, VarDict); t_from_form({type, _L, string, []}, _TypeNames, _RecDict, _VarDict) -> {t_string(), []}; t_from_form({type, _L, term, []}, _TypeNames, _RecDict, _VarDict) -> {t_any(), []}; -t_from_form({type, _L, tid, []}, _TypeNames, _RecDict, _VarDict) -> - {t_tid(), []}; +t_from_form({type, _L, tid, []}, TypeNames, RecDict, VarDict) -> + builtin_type(tid, t_tid(), TypeNames, RecDict, VarDict); t_from_form({type, _L, timeout, []}, _TypeNames, _RecDict, _VarDict) -> {t_timeout(), []}; t_from_form({type, _L, tuple, any}, _TypeNames, _RecDict, _VarDict) -> @@ -4322,36 +4327,46 @@ t_from_form({opaque, _L, Name, {Mod, Args, Rep}}, _TypeNames, _RecDict, _VarDict) -> {t_opaque(Mod, Name, Args, Rep), []}. +builtin_type(Name, Type, TypeNames, RecDict, VarDict) -> + case lookup_type(Name, 0, RecDict) of + {_, {_M, _T, _A}} -> + type_from_form(Name, [], TypeNames, RecDict, VarDict); + error -> + {Type, []} + end. + type_from_form(Name, Args, TypeNames, RecDict, VarDict) -> ArgsLen = length(Args), ArgTypes = forms_to_types(Args, TypeNames, RecDict, VarDict), case lookup_type(Name, ArgsLen, RecDict) of {type, {_Module, Type, ArgNames}} -> - case can_unfold_more({type, Name}, TypeNames) of + TypeName = {type, Name, ArgsLen}, + case can_unfold_more(TypeName, TypeNames) of true -> List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), - {T, R} = t_from_form(Type, [{type, Name}|TypeNames], + {T, R} = t_from_form(Type, [TypeName|TypeNames], RecDict, TmpVarDict), - case lists:member({type, Name}, R) of + case lists:member(TypeName, R) of true -> {t_limit(T, ?REC_TYPE_LIMIT), R}; false -> {T, R} end; - false -> {t_any(), [{type, Name}]} + false -> {t_any(), [TypeName]} end; {opaque, {Module, Type, ArgNames}} -> + TypeName = {opaque, Name, ArgsLen}, {Rep, Rret} = - case can_unfold_more({opaque, Name}, TypeNames) of + case can_unfold_more(TypeName, TypeNames) of true -> List = lists:zip(ArgNames, ArgTypes), TmpVarDict = dict:from_list(List), - {T, R} = t_from_form(Type, [{opaque, Name}|TypeNames], + {T, R} = t_from_form(Type, [TypeName|TypeNames], RecDict, TmpVarDict), - case lists:member({opaque, Name}, R) of + case lists:member(TypeName, R) of true -> {t_limit(T, ?REC_TYPE_LIMIT), R}; false -> {T, R} end; - false -> {t_any(), [{opaque, Name}]} + false -> {t_any(), [TypeName]} end, Args2 = [subst_all_vars_to_any(ArgType) || ArgType <- ArgTypes], {skip_opaque_alias(Rep, Module, Name, Args2), Rret}; @@ -4588,7 +4603,7 @@ is_erl_type(?unit) -> true; is_erl_type(#c{}) -> true; is_erl_type(_) -> false. --spec lookup_record(atom(), dict()) -> +-spec lookup_record(atom(), type_table()) -> 'error' | {'ok', [{atom(), parse_form() | erl_type()}]}. lookup_record(Tag, RecDict) when is_atom(Tag) -> @@ -4603,7 +4618,8 @@ lookup_record(Tag, RecDict) when is_atom(Tag) -> error end. --spec lookup_record(atom(), arity(), dict()) -> 'error' | {'ok', [{atom(), erl_type()}]}. +-spec lookup_record(atom(), arity(), type_table()) -> + 'error' | {'ok', [{atom(), erl_type()}]}. lookup_record(Tag, Arity, RecDict) when is_atom(Tag) -> case dict:find({record, Tag}, RecDict) of @@ -4622,7 +4638,8 @@ lookup_type(Name, Arity, RecDict) -> {ok, Found} -> {type, Found} end. --spec type_is_defined('type' | 'opaque', atom(), arity(), dict()) -> boolean(). +-spec type_is_defined('type' | 'opaque', atom(), arity(), type_table()) -> + boolean(). type_is_defined(TypeOrOpaque, Name, Arity, RecDict) -> dict:is_key({TypeOrOpaque, Name, Arity}, RecDict). @@ -4654,10 +4671,17 @@ do_opaque(?union(List) = Type, Opaques, Pred) -> do_opaque(Type, _Opaques, Pred) -> Pred(Type). -is_same_type_name({Mod, Name, Args}, {Mod, Name, Args}) -> true; +is_same_type_name(ModNameArgs, ModNameArgs) -> true; +is_same_type_name({Mod, Name, Args1}, {Mod, Name, Args2}) -> + all_any(Args1) orelse all_any(Args2); is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) -> is_same_type_name2(Mod1, Name1, Args1, Mod2, Name2, Args2). +all_any([]) -> true; +all_any([T|L]) -> + t_is_any(T) andalso all_any(L); +all_any(_) -> false. + %% Compatibility. In Erlang/OTP 17 the pre-defined opaque types %% digraph() and so on can be used, but there are also new types such %% as digraph:graph() with the exact same meaning. In Erlang/OTP R18.0 @@ -4665,10 +4689,10 @@ is_same_type_name({Mod1, Name1, Args1}, {Mod2, Name2, Args2}) -> is_same_type_name2(digraph, digraph, [], digraph, graph, []) -> true; is_same_type_name2(digraph, graph, [], digraph, digraph, []) -> true; -is_same_type_name2(gb_sets, gb_set, [], gb_sets, set, [?any]) -> true; -is_same_type_name2(gb_sets, set, [?any], gb_sets, gb_set, []) -> true; -is_same_type_name2(gb_trees, gb_tree, [], gb_trees, tree, [?any, ?any]) -> true; -is_same_type_name2(gb_trees, tree, [?any, ?any], gb_trees, gb_tree, []) -> true; +is_same_type_name2(gb_sets, gb_set, [], gb_sets, set, [_]) -> true; +is_same_type_name2(gb_sets, set, [_], gb_sets, gb_set, []) -> true; +is_same_type_name2(gb_trees, gb_tree, [], gb_trees, tree, [_, _]) -> true; +is_same_type_name2(gb_trees, tree, [_, _], gb_trees, gb_tree, []) -> true; is_same_type_name2(_, _, _, _, _, _) -> false. %% ----------------------------------- diff --git a/lib/hipe/flow/cfg.hrl b/lib/hipe/flow/cfg.hrl index 95bf5f7194..1f7a162f27 100644 --- a/lib/hipe/flow/cfg.hrl +++ b/lib/hipe/flow/cfg.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -42,12 +42,12 @@ %% %% Data is a triple with a dict of constants, a list of labels and an integer %% --type cfg_data() :: {dict(), [cfg_lbl()], non_neg_integer()}. +-type cfg_data() :: {dict:dict(), [cfg_lbl()], non_neg_integer()}. %% %% The following is to be used by other modules %% --record(cfg, {table = gb_trees:empty() :: gb_tree(), +-record(cfg, {table = gb_trees:empty() :: gb_trees:tree(), info :: #cfg_info{}, data :: cfg_data()}). -type cfg() :: #cfg{}. diff --git a/lib/hipe/flow/cfg.inc b/lib/hipe/flow/cfg.inc index 62f399a81c..f0b1a75737 100644 --- a/lib/hipe/flow/cfg.inc +++ b/lib/hipe/flow/cfg.inc @@ -4,7 +4,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -534,7 +534,7 @@ breadth_list([], Vis, _CFG, BO) -> {Vis, BO}. -endif. --spec none_visited() -> gb_set(). +-spec none_visited() -> gb_sets:set(). none_visited() -> gb_sets:empty(). diff --git a/lib/hipe/flow/hipe_dominators.erl b/lib/hipe/flow/hipe_dominators.erl index 113a32c3b7..50d45c7c72 100644 --- a/lib/hipe/flow/hipe_dominators.erl +++ b/lib/hipe/flow/hipe_dominators.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -57,7 +57,7 @@ -record(domTree, {root :: cfg_lbl(), size = 0 :: non_neg_integer(), - nodes = gb_trees:empty() :: gb_tree()}). + nodes = gb_trees:empty() :: gb_trees:tree()}). -type domTree() :: #domTree{}. %%>----------------------------------------------------------------------< @@ -590,7 +590,7 @@ domTree_pp_children([], _) -> %% %%======================================================================== --type domFrontier() :: gb_tree(). +-type domFrontier() :: gb_trees:tree(). %%>----------------------------------------------------------------------< %% Procedure : domFrontier_create diff --git a/lib/hipe/flow/liveness.inc b/lib/hipe/flow/liveness.inc index 9c5eaf3e68..6f161fb269 100644 --- a/lib/hipe/flow/liveness.inc +++ b/lib/hipe/flow/liveness.inc @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -71,7 +71,7 @@ %% The generic liveness analysis %% --spec analyze(cfg()) -> gb_tree(). +-spec analyze(cfg()) -> gb_trees:tree(). -ifdef(HIPE_LIVENESS_CALC_LARGEST_LIVESET). analyze(CFG) -> @@ -209,7 +209,7 @@ successors(L, Liveness) -> {_GK, _LiveIn, Successors} = liveness_lookup(L, Liveness), Successors. --spec livein(gb_tree(), _) -> [_]. +-spec livein(gb_trees:tree(), _) -> [_]. livein(Liveness, L) -> {_GK, LiveIn, _Successors} = liveness_lookup(L, Liveness), diff --git a/lib/hipe/icode/hipe_icode_callgraph.erl b/lib/hipe/icode/hipe_icode_callgraph.erl index 5789328f47..ccf97ecc17 100644 --- a/lib/hipe/icode/hipe_icode_callgraph.erl +++ b/lib/hipe/icode/hipe_icode_callgraph.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -46,7 +46,7 @@ -type mfa_icode() :: {mfa(), #icode{}}. --record(icode_callgraph, {codedict :: dict(), ordered_sccs :: [[mfa()]]}). +-record(icode_callgraph, {codedict :: dict:dict(), ordered_sccs :: [[mfa()]]}). %%------------------------------------------------------------------------ %% Exported functions diff --git a/lib/hipe/icode/hipe_icode_cfg.erl b/lib/hipe/icode/hipe_icode_cfg.erl index 9b4a10e273..f6c2b0600b 100644 --- a/lib/hipe/icode/hipe_icode_cfg.erl +++ b/lib/hipe/icode/hipe_icode_cfg.erl @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -54,8 +54,8 @@ -spec postorder(cfg()) -> [icode_lbl()]. -spec reverse_postorder(cfg()) -> [icode_lbl()]. --spec is_visited(icode_lbl(), gb_set()) -> boolean(). --spec visit(icode_lbl(), gb_set()) -> gb_set(). +-spec is_visited(icode_lbl(), gb_sets:set()) -> boolean(). +-spec visit(icode_lbl(), gb_sets:set()) -> gb_sets:set(). -spec bb(cfg(), icode_lbl()) -> 'not_found' | bb(). -spec bb_add(cfg(), icode_lbl(), bb()) -> cfg(). diff --git a/lib/hipe/icode/hipe_icode_coordinator.erl b/lib/hipe/icode/hipe_icode_coordinator.erl index 79e3304e6f..c69db9afa9 100644 --- a/lib/hipe/icode/hipe_icode_coordinator.erl +++ b/lib/hipe/icode/hipe_icode_coordinator.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -49,9 +49,9 @@ coordinate(CG, Escaping, NonEscaping, Mod) -> -type mfalists() :: {[mfa()], [mfa()]}. --spec coordinate(mfalists(), hipe_digraph:hdg(), gb_tree(), - fun((mfalists(), gb_tree()) -> mfalists()), - fun((gb_tree()) -> 'ok'), pid()) -> no_return(). +-spec coordinate(mfalists(), hipe_digraph:hdg(), gb_trees:tree(), + fun((mfalists(), gb_trees:tree()) -> mfalists()), + fun((gb_trees:tree()) -> 'ok'), pid()) -> no_return(). coordinate(MFALists, CG, PM, Restart, LastAction, ServerPid) -> case MFALists of diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl index 00caffb24b..6191c536ad 100644 --- a/lib/hipe/icode/hipe_icode_exceptions.erl +++ b/lib/hipe/icode/hipe_icode_exceptions.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -397,9 +397,9 @@ get_renaming(C, Map) -> succ :: #cfg{}, pred :: #cfg{}, start_labels :: [icode_lbl(),...], - visited = hipe_icode_cfg:none_visited() :: gb_set(), - out = gb_trees:empty() :: gb_tree(), - in = gb_trees:empty() :: gb_tree() + visited = hipe_icode_cfg:none_visited() :: gb_sets:set(), + out = gb_trees:empty() :: gb_trees:tree(), + in = gb_trees:empty() :: gb_trees:tree() }). init_state(CFG) -> diff --git a/lib/hipe/icode/hipe_icode_fp.erl b/lib/hipe/icode/hipe_icode_fp.erl index a2ca6132d1..c0cd9bd2d1 100644 --- a/lib/hipe/icode/hipe_icode_fp.erl +++ b/lib/hipe/icode/hipe_icode_fp.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -33,8 +33,8 @@ -include("hipe_icode.hrl"). -include("../flow/cfg.hrl"). --record(state, {edge_map = gb_trees:empty() :: gb_tree(), - fp_ebb_map = gb_trees:empty() :: gb_tree(), +-record(state, {edge_map = gb_trees:empty() :: gb_trees:tree(), + fp_ebb_map = gb_trees:empty() :: gb_trees:tree(), cfg :: #cfg{}}). %%-------------------------------------------------------------------- diff --git a/lib/hipe/icode/hipe_icode_instruction_counter.erl b/lib/hipe/icode/hipe_icode_instruction_counter.erl index 92658d294a..f44adfe149 100644 --- a/lib/hipe/icode/hipe_icode_instruction_counter.erl +++ b/lib/hipe/icode/hipe_icode_instruction_counter.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -64,7 +64,8 @@ walktrough_bb(BB, Info) -> %% The counter specific functions %%------------------------------------------------------------------- --spec compare(gb_tree(), gb_tree(), gb_tree()) -> gb_tree(). +-spec compare(gb_trees:tree(), gb_trees:tree(), gb_trees:tree()) -> + gb_trees:tree(). compare(Name, Old, New) -> NewList = gb_trees:to_list(New), diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl index 1a2cbfae31..fbc58f3568 100644 --- a/lib/hipe/icode/hipe_icode_range.erl +++ b/lib/hipe/icode/hipe_icode_range.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -72,8 +72,8 @@ -type final_fun() :: fun((mfa(), [range()]) -> 'ok'). -type data() :: {mfa(), args_fun(), call_fun(), final_fun()}. -type label() :: non_neg_integer(). --type info() :: gb_tree(). --type work_list() :: {[label()], [label()], set()}. +-type info() :: gb_trees:tree(). +-type work_list() :: {[label()], [label()], sets:set()}. -type variable() :: #icode_variable{}. -type annotated_variable() :: #icode_variable{}. -type argument() :: #icode_const{} | variable(). @@ -82,9 +82,9 @@ -type last_instr_return() :: {instr_split_info(), range()}. -record(state, {info_map = gb_trees:empty() :: info(), - counter = dict:new() :: dict(), + counter = dict:new() :: dict:dict(), cfg :: cfg(), - liveness = gb_trees:empty() :: gb_tree(), + liveness = gb_trees:empty() :: gb_trees:tree(), ret_type :: range(), lookup_fun :: call_fun(), result_action :: final_fun()}). diff --git a/lib/hipe/icode/hipe_icode_ssa.erl b/lib/hipe/icode/hipe_icode_ssa.erl index 4607a96dda..2c4b6d9409 100644 --- a/lib/hipe/icode/hipe_icode_ssa.erl +++ b/lib/hipe/icode/hipe_icode_ssa.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,7 +37,7 @@ -include("../ssa/hipe_ssa.inc"). %% Declarations for exported functions which are Icode-specific. --spec ssa_liveness__analyze(#cfg{}) -> gb_tree(). +-spec ssa_liveness__analyze(#cfg{}) -> gb_trees:tree(). -spec ssa_liveness__livein(_, icode_lbl()) -> [#icode_variable{}]. %% -spec ssa_liveness__livein(_, icode_lbl(), _) -> [#icode_var{}]. diff --git a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl index 2337ef9323..772e30eada 100644 --- a/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl +++ b/lib/hipe/icode/hipe_icode_ssa_struct_reuse.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2013. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -70,9 +70,9 @@ %% var - maps variables to expression value numbers. These variables are %% defined or used by the structure expressions. --record(maps, {var = gb_trees:empty() :: gb_tree(), - instr = gb_trees:empty() :: gb_tree(), - expr = gb_trees:empty() :: gb_tree()}). +-record(maps, {var = gb_trees:empty() :: gb_trees:tree(), + instr = gb_trees:empty() :: gb_trees:tree(), + expr = gb_trees:empty() :: gb_trees:tree()}). maps_var(#maps{var = Out}) -> Out. maps_instr(#maps{instr = Out}) -> Out. @@ -211,10 +211,10 @@ varinfo_use_add(#varinfo{use = UseSet} = I, Use) -> pred = none :: 'none' | [icode_lbl()], succ = none :: 'none' | [icode_lbl()], code = [] :: [tuple()], % [illegal_icode_instr()] - phi = gb_trees:empty() :: gb_tree(), + phi = gb_trees:empty() :: gb_trees:tree(), varmap = [] :: [{icode_var(), icode_var()}], pre_loop = false :: boolean(), - non_struct_defs = gb_sets:new() :: gb_set(), + non_struct_defs = gb_sets:new() :: gb_sets:set(), up_expr = none :: 'none' | ?SETS:?SET(_), killed_expr = none :: 'none' | ?SETS:?SET(_), sub_inserts = ?SETS:new() :: ?SETS:?SET(_), @@ -319,7 +319,7 @@ node_create(Label, Pred, Succ) -> start_label = none :: 'none' | icode_lbl(), rev_postorder = none :: 'none' | [icode_lbl()], all_expr = none :: 'none' | [non_neg_integer()], - tree = gb_trees:empty() :: gb_tree()}). + tree = gb_trees:empty() :: gb_trees:tree()}). nodes_postorder(#nodes{postorder = Out}) -> Out. nodes_rev_postorder(#nodes{rev_postorder = Out}) -> Out. @@ -356,7 +356,7 @@ nodes_create() -> #nodes{}. %% del_red_test - flag that is set to true when the reduction test %% has been inserted is used to move the reduction test. --record(update, {inserted = gb_trees:empty() :: gb_tree(), +-record(update, {inserted = gb_trees:empty() :: gb_trees:tree(), del_red_test = false :: boolean()}). update_inserted_lookup(#update{inserted = Inserted}, ExprId) -> diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl index 046949d2f2..65876b83ea 100644 --- a/lib/hipe/icode/hipe_icode_type.erl +++ b/lib/hipe/icode/hipe_icode_type.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2012. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -97,9 +97,9 @@ t_pid/0, t_port/0, t_reference/0, t_subtract/2, t_sup/2, t_to_tlist/1, t_tuple/0, t_tuple/1, t_tuple_sizes/1]). --record(state, {info_map = gb_trees:empty() :: gb_tree(), +-record(state, {info_map = gb_trees:empty() :: gb_trees:tree(), cfg :: cfg(), - liveness = gb_trees:empty() :: gb_tree(), + liveness = gb_trees:empty() :: gb_trees:tree(), arg_types :: [erl_types:erl_type()], ret_type = [t_none()] :: [erl_types:erl_type()], lookupfun :: call_fun(), diff --git a/lib/hipe/misc/hipe_consttab.erl b/lib/hipe/misc/hipe_consttab.erl index c381e6a057..2b02f54b5c 100644 --- a/lib/hipe/misc/hipe_consttab.erl +++ b/lib/hipe/misc/hipe_consttab.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -462,7 +462,7 @@ update_referred_labels(Table, LabelMap) -> tree_keys(T) -> dict:fetch_keys(T). --spec tree_to_list(dict()) -> [{_, _}]. +-spec tree_to_list(dict:dict()) -> [{_, _}]. tree_to_list(T) -> dict:to_list(T). @@ -486,11 +486,11 @@ tree_lookup(Key, T) -> none end. --spec tree_empty() -> dict(). +-spec tree_empty() -> dict:dict(). tree_empty() -> dict:new(). --spec tree_lookup_key_for_value(ctdata(), dict()) -> 'none' | {'value', _}. +-spec tree_lookup_key_for_value(ctdata(), dict:dict()) -> 'none' | {'value', _}. tree_lookup_key_for_value(Val, T) -> tree_lookup_key_for_value_1(tree_to_list(T), Val). diff --git a/lib/hipe/misc/hipe_consttab.hrl b/lib/hipe/misc/hipe_consttab.hrl index 39018dac34..aea3c5bc88 100644 --- a/lib/hipe/misc/hipe_consttab.hrl +++ b/lib/hipe/misc/hipe_consttab.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -22,6 +22,6 @@ -type ct_alignment() :: 4 | 8. -type hipe_constlbl() :: non_neg_integer(). --type hipe_consttab() :: {dict(), [hipe_constlbl()], hipe_constlbl()}. +-type hipe_consttab() :: {dict:dict(), [hipe_constlbl()], hipe_constlbl()}. %%----------------------------------------------------------------------------- diff --git a/lib/hipe/misc/hipe_pack_constants.erl b/lib/hipe/misc/hipe_pack_constants.erl index e214d7ebbc..ca8a9e6bf7 100644 --- a/lib/hipe/misc/hipe_pack_constants.erl +++ b/lib/hipe/misc/hipe_pack_constants.erl @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% Copyright Ericsson AB 2003-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -198,7 +198,7 @@ compact_dests([], Dest, AccofDest, Acc) -> slim_constmap(Map) -> slim_constmap(Map, gb_sets:new(), []). --spec slim_constmap([#pcm_entry{}], gb_set(), [raw_data()]) -> [raw_data()]. +-spec slim_constmap([#pcm_entry{}], gb_sets:set(), [raw_data()]) -> [raw_data()]. slim_constmap([#pcm_entry{const_num=ConstNo, start=Offset, type=Type, raw_data=Term}|Rest], Inserted, Acc) -> case gb_sets:is_member(ConstNo, Inserted) of diff --git a/lib/hipe/misc/hipe_sdi.erl b/lib/hipe/misc/hipe_sdi.erl index ef1b5b48c5..9a2ff78ecf 100644 --- a/lib/hipe/misc/hipe_sdi.erl +++ b/lib/hipe/misc/hipe_sdi.erl @@ -3,7 +3,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %%% %%% The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in @@ -50,7 +50,7 @@ -record(pass1, {prevSdi :: integer(), preS = [] :: [#pre_sdi_data{}], - labelMap = gb_trees:empty() :: gb_tree()}). + labelMap = gb_trees:empty() :: gb_trees:tree()}). -record(sdi_data, {address :: address(), label_address :: address(), @@ -105,11 +105,11 @@ pass1_add_sdi(Pass1, Address, Label, SdiInfo) -> PreSdiData = #pre_sdi_data{address=Address, label=Label, si=SdiInfo}, Pass1#pass1{prevSdi=PrevSdi+1, preS=[PreSdiData|PreS]}. --spec pass1_finalise(#pass1{}) -> {non_neg_integer(),tuple(),gb_tree()}. +-spec pass1_finalise(#pass1{}) -> {non_neg_integer(),tuple(),gb_trees:tree()}. pass1_finalise(#pass1{prevSdi=PrevSdi, preS=PreS, labelMap=LabelMap}) -> {PrevSdi+1, pass1_finalise_preS(PreS, LabelMap, []), LabelMap}. --spec pass1_finalise_preS([#pre_sdi_data{}], gb_tree(), [#sdi_data{}]) -> +-spec pass1_finalise_preS([#pre_sdi_data{}], gb_trees:tree(), [#sdi_data{}]) -> tuple(). pass1_finalise_preS([], _LabelMap, S) -> vector_from_list(S); pass1_finalise_preS([PreSdiData|PreS], LabelMap, S) -> @@ -122,7 +122,7 @@ pass1_finalise_preS([PreSdiData|PreS], LabelMap, S) -> %%% Pass2. --spec pass2(#pass1{}) -> {gb_tree(), non_neg_integer()}. +-spec pass2(#pass1{}) -> {gb_trees:tree(), non_neg_integer()}. pass2(Pass1) -> {N,SDIS,LabelMap} = pass1_finalise(Pass1), LONG = mk_long(N), @@ -339,13 +339,14 @@ initINCR(SdiNr, PrevIncr, N, LONG, INCREMENT) -> %%% a and previous sdi i is remapped to a+incr(i), where %%% incr(i) = if i < 0 then 0 else INCREMENT[i]. --spec adjust_label_map(gb_tree(), hipe_array()) -> gb_tree(). +-spec adjust_label_map(gb_trees:tree(), hipe_array()) -> gb_trees:tree(). adjust_label_map(LabelMap, INCREMENT) -> applyIncr(gb_trees:to_list(LabelMap), INCREMENT, gb_trees:empty()). -type label_pair() :: {label(), #label_data{}}. --spec applyIncr([label_pair()], hipe_array(), gb_tree()) -> gb_tree(). +-spec applyIncr([label_pair()], hipe_array(), gb_trees:tree()) -> + gb_trees:tree(). applyIncr([], _INCREMENT, LabelMap) -> LabelMap; applyIncr([{Label,LabelData}|List], INCREMENT, LabelMap) -> #label_data{address=Address, prevSdi=PrevSdi} = LabelData, diff --git a/lib/hipe/regalloc/hipe_ig_moves.erl b/lib/hipe/regalloc/hipe_ig_moves.erl index 186c87a690..ebc6ebc20d 100644 --- a/lib/hipe/regalloc/hipe_ig_moves.erl +++ b/lib/hipe/regalloc/hipe_ig_moves.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,7 +36,7 @@ -record(ig_moves, {movelist :: hipe_vector(), nrmoves = 0 :: non_neg_integer(), moveinsns = [] :: [{_,_}], - moveset = gb_sets:empty() :: gb_set()}). + moveset = gb_sets:empty() :: gb_sets:set()}). %%----------------------------------------------------------------------------- diff --git a/lib/hipe/ssa/hipe_ssa_const_prop.inc b/lib/hipe/ssa/hipe_ssa_const_prop.inc index 2fce384197..0876fca34a 100644 --- a/lib/hipe/ssa/hipe_ssa_const_prop.inc +++ b/lib/hipe/ssa/hipe_ssa_const_prop.inc @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -72,10 +72,10 @@ visit_expressions([Inst | Insts], Environment, FlowWork, SSAWork) -> %%----------------------------------------------------------------------------- -record(env, {cfg :: #cfg{}, - executable_flags = gb_sets:empty() :: gb_set(), - handled_blocks = gb_sets:empty() :: gb_set(), - lattice_values = gb_trees:empty() :: gb_tree(), - ssa_edges = gb_trees:empty() :: gb_tree() + executable_flags = gb_sets:empty() :: gb_sets:set(), + handled_blocks = gb_sets:empty() :: gb_sets:set(), + lattice_values = gb_trees:empty() :: gb_trees:tree(), + ssa_edges = gb_trees:empty() :: gb_trees:tree() }). create_env(CFG) -> diff --git a/lib/hipe/util/hipe_digraph.erl b/lib/hipe/util/hipe_digraph.erl index fcfaa64684..01b1f8c77c 100644 --- a/lib/hipe/util/hipe_digraph.erl +++ b/lib/hipe/util/hipe_digraph.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,10 +36,10 @@ -type ordset(T) :: [T]. % XXX: temporarily --record(hipe_digraph, {edges = dict:new() :: dict(), - rev_edges = dict:new() :: dict(), +-record(hipe_digraph, {edges = dict:new() :: dict:dict(), + rev_edges = dict:new() :: dict:dict(), leaves = ordsets:new() :: ordset(_), % ??? - nodes = sets:new() :: set()}). + nodes = sets:new() :: sets:set()}). -opaque hdg() :: #hipe_digraph{}. diff --git a/lib/hipe/util/hipe_dot.erl b/lib/hipe/util/hipe_dot.erl index e4a47ae0c4..94f7fd60cc 100644 --- a/lib/hipe/util/hipe_dot.erl +++ b/lib/hipe/util/hipe_dot.erl @@ -2,7 +2,7 @@ %%% %%% %CopyrightBegin% %%% -%%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%%% Copyright Ericsson AB 2004-2014. All Rights Reserved. %%% %%% The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in @@ -70,13 +70,13 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec translate_digraph(digraph(), string(), string()) -> 'ok'. +-spec translate_digraph(digraph:graph(), string(), string()) -> 'ok'. translate_digraph(G, FileName, GName) -> translate_digraph(G, FileName, GName, fun(X) -> io_lib:format("~p", [X]) end, []). --spec translate_digraph(digraph(), string(), string(), +-spec translate_digraph(digraph:graph(), string(), string(), fun((_) -> string()), [_]) -> 'ok'. translate_digraph(G, FileName, GName, Fun, Opts) -> diff --git a/lib/hipe/util/hipe_vectors.hrl b/lib/hipe/util/hipe_vectors.hrl index 043faf4c91..5e24db238d 100644 --- a/lib/hipe/util/hipe_vectors.hrl +++ b/lib/hipe/util/hipe_vectors.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -24,5 +24,5 @@ -endif. -ifdef(USE_GBTREES). --type hipe_vector() :: gb_tree(). +-type hipe_vector() :: gb_trees:tree(). -endif. diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 80c8b2439e..a89a457a51 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -55,8 +55,8 @@ headers, % #http_response_h{} body, % binary() mfa, % {Module, Function, Args} - pipeline = queue:new(), % queue() - keep_alive = queue:new(), % queue() + pipeline = queue:new(), % queue:queue() + keep_alive = queue:new(), % queue:queue() status, % undefined | new | pipeline | keep_alive | close | {ssl_tunnel, Request} canceled = [], % [RequestId] max_header_size = nolimit, % nolimit | integer() diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl index 7dc51495f7..2300b7e901 100644 --- a/lib/kernel/src/rpc.erl +++ b/lib/kernel/src/rpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -66,7 +66,7 @@ %%------------------------------------------------------------------------ --type state() :: gb_tree(). +-type state() :: gb_trees:tree(pid(), {pid(), reference()}). %%------------------------------------------------------------------------ diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl index adb2e1debe..341a4217e4 100644 --- a/lib/ssl/src/ssl_connection.hrl +++ b/lib/ssl/src/ssl_connection.hrl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2013. All Rights Reserved. +%% Copyright Ericsson AB 2013-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -73,7 +73,7 @@ renegotiation :: undefined | {boolean(), From::term() | internal | peer}, start_or_recv_from :: term(), timer :: undefined | reference(), % start_or_recive_timer - send_queue :: queue(), + send_queue :: queue:queue(), terminated = false ::boolean(), allow_renegotiate = true ::boolean(), expecting_next_protocol_negotiation = false ::boolean(), diff --git a/lib/stdlib/doc/src/array.xml b/lib/stdlib/doc/src/array.xml index b0b3aa6dc1..b03a2fa0cc 100644 --- a/lib/stdlib/doc/src/array.xml +++ b/lib/stdlib/doc/src/array.xml @@ -3,7 +3,7 @@
- 20072013 + 20072014 Ericsson AB. All Rights Reserved. @@ -84,13 +84,19 @@ the default value cannot be confused with the values of set entries.

{'EXIT',{badarg,_}} = (catch array:get(18, A3)). - array() +

A functional, extendible array. The representation is not documented and is subject to change without notice. Note that arrays cannot be directly compared for equality.

+ + + +

array() is equivalent to array(term()).

+
+
@@ -189,7 +195,7 @@ the default value cannot be confused with the values of set entries.

-

Convert an ordered list of pairs {Index, Value} to a +

Convert an ordered list of pairs {Index, Value} to a corresponding extendible array. Default is used as the value for uninitialized entries of the array. If Orddict is not a proper, ordered list of pairs whose first elements are nonnegative @@ -455,7 +461,7 @@ cannot be changed once the array has been created.

-

Convert the array to an ordered list of pairs {Index, Value}, +

Convert the array to an ordered list of pairs {Index, Value}, skipping default-valued entries.

See also: to_orddict/1.

@@ -476,7 +482,7 @@ cannot be changed once the array has been created.

-

Convert the array to an ordered list of pairs {Index, Value}. +

Convert the array to an ordered list of pairs {Index, Value}.

See also: from_orddict/2, sparse_to_orddict/1.

diff --git a/lib/stdlib/doc/src/dict.xml b/lib/stdlib/doc/src/dict.xml index 6ff81b56ee..942fd1f45e 100644 --- a/lib/stdlib/doc/src/dict.xml +++ b/lib/stdlib/doc/src/dict.xml @@ -4,7 +4,7 @@
- 19962013 + 19962014 Ericsson AB. All Rights Reserved. @@ -41,9 +41,15 @@ - dict() +

Dictionary as returned by new/0.

+ + + +

dict() is equivalent to dict(term(), term()).

+
+
diff --git a/lib/stdlib/doc/src/digraph.xml b/lib/stdlib/doc/src/digraph.xml index c5d5707f4f..9b9b48584b 100644 --- a/lib/stdlib/doc/src/digraph.xml +++ b/lib/stdlib/doc/src/digraph.xml @@ -4,7 +4,7 @@
- 19962013 + 19962014 Ericsson AB. All Rights Reserved. @@ -98,7 +98,7 @@ - digraph() +

A digraph as returned by new/0,1.

diff --git a/lib/stdlib/doc/src/gb_sets.xml b/lib/stdlib/doc/src/gb_sets.xml index 8ca95df8fc..ea96c14472 100644 --- a/lib/stdlib/doc/src/gb_sets.xml +++ b/lib/stdlib/doc/src/gb_sets.xml @@ -4,7 +4,7 @@
- 20012013 + 20012014 Ericsson AB. All Rights Reserved. @@ -115,28 +115,40 @@ - gb_set() +

A GB set.

- + + +

set() is equivalent to set(term()).

+
+
+ +

A GB set iterator.

+ + + +

iter() is equivalent to iter(term()).

+
+
- Add a (possibly existing) element to a gb_set + Add a (possibly existing) element to a set -

Returns a new gb_set formed from Set1 with +

Returns a new set formed from Set1 with Element inserted. If Element is already an element in Set1, nothing is changed.

- Rebalance tree representation of a gb_set + Rebalance tree representation of a set

Rebalances the tree representation of Set1. Note that this is rarely necessary, but may be motivated when a large @@ -148,9 +160,9 @@ - Remove an element from a gb_set + Remove an element from a set -

Returns a new gb_set formed from Set1 with +

Returns a new set formed from Set1 with Element removed. Assumes that Element is present in Set1.

@@ -158,9 +170,9 @@ - Remove a (possibly non-existing) element from a gb_set + Remove a (possibly non-existing) element from a set -

Returns a new gb_set formed from Set1 with +

Returns a new set formed from Set1 with Element removed. If Element is not an element in Set1, nothing is changed.

@@ -168,7 +180,7 @@ - Return the difference of two gb_sets + Return the difference of two sets

Returns only the elements of Set1 which are not also elements of Set2.

@@ -177,14 +189,14 @@ - Return an empty gb_set + Return an empty set -

Returns a new empty gb_set.

+

Returns a new empty set.

- Filter gb_set elements + Filter set elements

Filters elements in Set1 using predicate function Pred.

@@ -192,7 +204,7 @@
- Fold over gb_set elements + Fold over set elements

Folds Function over every element in Set returning the final value of the accumulator.

@@ -200,46 +212,46 @@
- Convert a list into a gb_set + Convert a list into a set -

Returns a gb_set of the elements in List, where +

Returns a set of the elements in List, where List may be unordered and contain duplicates.

- Make a gb_set from an ordset list + Make a set from an ordset list -

Turns an ordered-set list List into a gb_set. The list +

Turns an ordered-set list List into a set. The list must not contain duplicates.

- Add a new element to a gb_set + Add a new element to a set -

Returns a new gb_set formed from Set1 with +

Returns a new set formed from Set1 with Element inserted. Assumes that Element is not present in Set1.

- Return the intersection of two gb_sets + Return the intersection of two sets

Returns the intersection of Set1 and Set2.

- Return the intersection of a list of gb_sets + Return the intersection of a list of sets -

Returns the intersection of the non-empty list of gb_sets.

+

Returns the intersection of the non-empty list of sets.

- Check whether two gb_sets are disjoint + Check whether two sets are disjoint

Returns true if Set1 and Set2 are disjoint (have no elements in common), @@ -248,7 +260,7 @@ - Test for empty gb_set + Test for empty set

Returns true if Set is an empty set, and false otherwise.

@@ -257,7 +269,7 @@ - Test for membership of a gb_set + Test for membership of a set

Returns true if Element is an element of Set, otherwise false.

@@ -265,9 +277,9 @@
- Test for a gb_set + Test for a set -

Returns true if Term appears to be a gb_set, +

Returns true if Term appears to be a set, otherwise false.

@@ -281,7 +293,7 @@
- Return an iterator for a gb_set + Return an iterator for a set

Returns an iterator that can be used for traversing the entries of Set; see next/1. The implementation @@ -303,7 +315,7 @@ - Traverse a gb_set with an iterator + Traverse a set with an iterator

Returns {Element, Iter2} where Element is the smallest element referred to by the iterator Iter1, @@ -314,14 +326,14 @@ - Return a gb_set with one element + Return a set with one element -

Returns a gb_set containing only the element Element.

+

Returns a set containing only the element Element.

- Return the number of elements in a gb_set + Return the number of elements in a set

Returns the number of elements in Set.

@@ -356,24 +368,24 @@
- Convert a gb_set into a list + Convert a set into a list

Returns the elements of Set as a list.

- Return the union of two gb_sets + Return the union of two sets -

Returns the merged (union) gb_set of Set1 and +

Returns the merged (union) set of Set1 and Set2.

- Return the union of a list of gb_sets + Return the union of a list of sets -

Returns the merged (union) gb_set of the list of gb_sets.

+

Returns the merged (union) set of the list of sets.

diff --git a/lib/stdlib/doc/src/gb_trees.xml b/lib/stdlib/doc/src/gb_trees.xml index 57e60eacb7..b2f237e1d7 100644 --- a/lib/stdlib/doc/src/gb_trees.xml +++ b/lib/stdlib/doc/src/gb_trees.xml @@ -4,7 +4,7 @@
- 20012013 + 20012014 Ericsson AB. All Rights Reserved. @@ -59,13 +59,25 @@ - gb_tree() +

A GB tree.

- + + +

tree() is equivalent to tree(term(), term()).

+
+
+ +

A GB tree iterator.

+ + + +

iter() is equivalent to iter(term(), term()).

+
+
@@ -108,9 +120,9 @@ Insert or update key with value in a tree -

Inserts Key with value Val into Tree1 if +

Inserts Key with value Value into Tree1 if the key is not present in the tree, otherwise updates - Key to value Val in Tree1. Returns the + Key to value Value in Tree1. Returns the new tree.

@@ -135,7 +147,7 @@ Insert a new key and value in a tree -

Inserts Key with value Val into Tree1; +

Inserts Key with value Value into Tree1; returns the new tree. Assumes that the key is not present in the tree, crashes otherwise.

@@ -181,8 +193,8 @@ Return largest key and value -

Returns {Key, Val}, where Key is the largest - key in Tree, and Val is the value associated +

Returns {Key, Value}, where Key is the largest + key in Tree, and Value is the value associated with this key. Assumes that the tree is nonempty.

@@ -191,7 +203,7 @@ Look up a key in a tree

Looks up Key in Tree; returns - {value, Val}, or none if Key is not + {value, Value}, or none if Key is not present.

@@ -207,7 +219,7 @@ Traverse a tree with an iterator -

Returns {Key, Val, Iter2} where Key is the +

Returns {Key, Value, Iter2} where Key is the smallest key referred to by the iterator Iter1, and Iter2 is the new iterator to be used for traversing the remaining nodes, or the atom none if no @@ -225,8 +237,8 @@ Return smallest key and value -

Returns {Key, Val}, where Key is the smallest - key in Tree, and Val is the value associated +

Returns {Key, Value}, where Key is the smallest + key in Tree, and Value is the value associated with this key. Assumes that the tree is nonempty.

@@ -234,8 +246,8 @@ Extract largest key and value -

Returns {Key, Val, Tree2}, where Key is the - largest key in Tree1, Val is the value +

Returns {Key, Value, Tree2}, where Key is the + largest key in Tree1, Value is the value associated with this key, and Tree2 is this tree with the corresponding node deleted. Assumes that the tree is nonempty.

@@ -245,8 +257,8 @@ Extract smallest key and value -

Returns {Key, Val, Tree2}, where Key is the - smallest key in Tree1, Val is the value +

Returns {Key, Value, Tree2}, where Key is the + smallest key in Tree1, Value is the value associated with this key, and Tree2 is this tree with the corresponding node deleted. Assumes that the tree is nonempty.

@@ -263,7 +275,7 @@ Update a key to new value in a tree -

Updates Key to value Val in Tree1; +

Updates Key to value Value in Tree1; returns the new tree. Assumes that the key is present in the tree.

diff --git a/lib/stdlib/doc/src/queue.xml b/lib/stdlib/doc/src/queue.xml index bcf063bf0f..9c994154d4 100644 --- a/lib/stdlib/doc/src/queue.xml +++ b/lib/stdlib/doc/src/queue.xml @@ -4,7 +4,7 @@
- 19962013 + 19962014 Ericsson AB. All Rights Reserved. @@ -90,9 +90,15 @@ - queue() +

As returned by new/0.

+ + + +

queue() is equivalent to queue(term()).

+
+
diff --git a/lib/stdlib/doc/src/sets.xml b/lib/stdlib/doc/src/sets.xml index 4b220bdd85..c5b8dce4b7 100644 --- a/lib/stdlib/doc/src/sets.xml +++ b/lib/stdlib/doc/src/sets.xml @@ -4,7 +4,7 @@
- 20002013 + 20002014 Ericsson AB. All Rights Reserved. @@ -45,9 +45,15 @@ - set() +

As returned by new/0.

+ + + +

set() is equivalent to set(term()).

+
+
diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 2f69e2b0a4..10d2ccea45 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -86,6 +86,8 @@ foldr/3, sparse_foldl/3, sparse_foldr/3, fix/1, relax/1, is_fix/1, resize/1, resize/2]). +-export_type([array/0, array/1]). + %%-define(TEST,1). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -144,18 +146,28 @@ %%-------------------------------------------------------------------------- +-type element_tuple(T) :: + {T, T, T, T, T, T, T, T, T, T} + | {element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), element_tuple(T), element_tuple(T), + element_tuple(T), non_neg_integer()}. + +-type elements(T) :: non_neg_integer() + | element_tuple(T) + | nil(). % kill reference, for GC + -record(array, {size :: non_neg_integer(), %% number of defined entries max :: non_neg_integer(), %% maximum number of entries %% in current tree default, %% the default value (usually 'undefined') - elements %% the tuple tree + elements :: elements(_) %% the tuple tree }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #array{} -%% structure and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque array() :: #array{}. + +-opaque array() :: array(term()). + +-opaque array(Type) :: + #array{default :: Type, elements :: elements(Type)}. %% %% Types @@ -164,13 +176,13 @@ -type array_indx() :: non_neg_integer(). -type array_opt() :: {'fixed', boolean()} | 'fixed' - | {'default', Value :: term()} + | {'default', Type :: term()} | {'size', N :: non_neg_integer()} | (N :: non_neg_integer()). -type array_opts() :: array_opt() | [array_opt()]. --type indx_pair() :: {Index :: array_indx(), Value :: term()}. --type indx_pairs() :: [indx_pair()]. +-type indx_pair(Type) :: {Index :: array_indx(), Type}. +-type indx_pairs(Type) :: [indx_pair(Type)]. %%-------------------------------------------------------------------------- @@ -321,7 +333,7 @@ size(_) -> erlang:error(badarg). %% %% @see new/2 --spec default(Array :: array()) -> term(). +-spec default(Array :: array(Type)) -> Value :: Type. default(#array{default = D}) -> D; default(_) -> erlang:error(badarg). @@ -404,7 +416,7 @@ new_test_() -> %% automatically upon insertion; see also {@link set/3}. %% @see relax/1 --spec fix(Array :: array()) -> array(). +-spec fix(Array :: array(Type)) -> array(Type). fix(#array{}=A) -> A#array{max = 0}. @@ -452,7 +464,7 @@ fix_test_() -> %% fix/1}.) %% @see fix/1 --spec relax(Array :: array()) -> array(). +-spec relax(Array :: array(Type)) -> array(Type). relax(#array{size = N}=A) -> A#array{max = find_max(N-1, ?LEAFSIZE)}. @@ -477,7 +489,8 @@ relax_test_() -> %% integer, the call fails with reason `badarg'. If the given array has %% fixed size, the resulting array will also have fixed size. --spec resize(Size :: non_neg_integer(), Array :: array()) -> array(). +-spec resize(Size :: non_neg_integer(), Array :: array(Type)) -> + array(Type). resize(Size, #array{size = N, max = M, elements = E}=A) when is_integer(Size), Size >= 0 -> @@ -508,7 +521,7 @@ resize(_Size, _) -> %% @see resize/2 %% @see sparse_size/1 --spec resize(Array :: array()) -> array(). +-spec resize(Array :: array(Type)) -> array(Type). resize(Array) -> resize(sparse_size(Array), Array). @@ -558,7 +571,7 @@ resize_test_() -> %% @see get/2 %% @see reset/2 --spec set(I :: array_indx(), Value :: term(), Array :: array()) -> array(). +-spec set(I :: array_indx(), Value :: Type, Array :: array(Type)) -> array(Type). set(I, Value, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -621,7 +634,7 @@ expand(I, _S, X, D) -> %% @see set/3 --spec get(I :: array_indx(), Array :: array()) -> term(). +-spec get(I :: array_indx(), Array :: array(Type)) -> Value :: Type. get(I, #array{size = N, max = M, elements = E, default = D}) when is_integer(I), I >= 0 -> @@ -661,7 +674,7 @@ get_1(I, E, _D) -> %% TODO: a reset_range function --spec reset(I :: array_indx(), Array :: array()) -> array(). +-spec reset(I :: array_indx(), Array :: array(Type)) -> array(Type). reset(I, #array{size = N, max = M, default = D, elements = E}=A) when is_integer(I), I >= 0 -> @@ -747,7 +760,7 @@ set_get_test_() -> %% @see from_list/2 %% @see sparse_to_list/1 --spec to_list(Array :: array()) -> list(). +-spec to_list(Array :: array(Type)) -> list(Value :: Type). to_list(#array{size = 0}) -> []; @@ -820,7 +833,7 @@ to_list_test_() -> %% %% @see to_list/1 --spec sparse_to_list(Array :: array()) -> list(). +-spec sparse_to_list(Array :: array(Type)) -> list(Value :: Type). sparse_to_list(#array{size = 0}) -> []; @@ -887,7 +900,7 @@ sparse_to_list_test_() -> %% @equiv from_list(List, undefined) --spec from_list(List :: list()) -> array(). +-spec from_list(List :: list(Value :: Type)) -> array(Type). from_list(List) -> from_list(List, undefined). @@ -899,7 +912,7 @@ from_list(List) -> %% @see new/2 %% @see to_list/1 --spec from_list(List :: list(), Default :: term()) -> array(). +-spec from_list(List :: list(Value :: Type), Default :: term()) -> array(Type). from_list([], Default) -> new({default,Default}); @@ -998,7 +1011,7 @@ from_list_test_() -> %% @see from_orddict/2 %% @see sparse_to_orddict/1 --spec to_orddict(Array :: array()) -> indx_pairs(). +-spec to_orddict(Array :: array(Type)) -> indx_pairs(Value :: Type). to_orddict(#array{size = 0}) -> []; @@ -1035,16 +1048,16 @@ to_orddict_3(N, R, D, L, E, S) -> to_orddict_2(element(N, E), R, D, L), E, S). --spec push_pairs(non_neg_integer(), array_indx(), term(), indx_pairs()) -> - indx_pairs(). +-spec push_pairs(non_neg_integer(), array_indx(), term(), indx_pairs(Type)) -> + indx_pairs(Type). push_pairs(0, _I, _E, L) -> L; push_pairs(N, I, E, L) -> push_pairs(N-1, I-1, E, [{I, E} | L]). --spec push_tuple_pairs(non_neg_integer(), array_indx(), term(), indx_pairs()) -> - indx_pairs(). +-spec push_tuple_pairs(non_neg_integer(), array_indx(), term(), indx_pairs(Type)) -> + indx_pairs(Type). push_tuple_pairs(0, _I, _T, L) -> L; @@ -1090,7 +1103,7 @@ to_orddict_test_() -> %% %% @see to_orddict/1 --spec sparse_to_orddict(Array :: array()) -> indx_pairs(). +-spec sparse_to_orddict(Array :: array(Type)) -> indx_pairs(Value :: Type). sparse_to_orddict(#array{size = 0}) -> []; @@ -1128,7 +1141,7 @@ sparse_to_orddict_3(N, R, D, L, E, S) -> E, S). -spec sparse_push_tuple_pairs(non_neg_integer(), array_indx(), - _, _, indx_pairs()) -> indx_pairs(). + _, _, indx_pairs(Type)) -> indx_pairs(Type). sparse_push_tuple_pairs(0, _I, _D, _T, L) -> L; @@ -1170,7 +1183,7 @@ sparse_to_orddict_test_() -> %% @equiv from_orddict(Orddict, undefined) --spec from_orddict(Orddict :: indx_pairs()) -> array(). +-spec from_orddict(Orddict :: indx_pairs(Value :: Type)) -> array(Type). from_orddict(Orddict) -> from_orddict(Orddict, undefined). @@ -1184,7 +1197,8 @@ from_orddict(Orddict) -> %% @see new/2 %% @see to_orddict/1 --spec from_orddict(Orddict :: indx_pairs(), Default :: term()) -> array(). +-spec from_orddict(Orddict :: indx_pairs(Value :: Type), Default :: Type) -> + array(Type). from_orddict([], Default) -> new({default,Default}); @@ -1379,8 +1393,8 @@ from_orddict_test_() -> %% @see foldr/3 %% @see sparse_map/2 --spec map(Function, Array :: array()) -> array() when - Function :: fun((Index :: array_indx(), Value :: _) -> _). +-spec map(Function, Array :: array(Type1)) -> array(Type2) when + Function :: fun((Index :: array_indx(), Type1) -> Type2). map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1471,8 +1485,8 @@ map_test_() -> %% %% @see map/2 --spec sparse_map(Function, Array :: array()) -> array() when - Function :: fun((Index :: array_indx(), Value :: _) -> _). +-spec sparse_map(Function, Array :: array(Type1)) -> array(Type2) when + Function :: fun((Index :: array_indx(), Type1) -> Type2). sparse_map(Function, Array=#array{size = N, elements = E, default = D}) when is_function(Function, 2) -> @@ -1567,8 +1581,8 @@ sparse_map_test_() -> %% @see map/2 %% @see sparse_foldl/3 --spec foldl(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1640,8 +1654,8 @@ foldl_test_() -> %% @see foldl/3 %% @see sparse_foldr/3 --spec sparse_foldl(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec sparse_foldl(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldl(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1717,8 +1731,8 @@ sparse_foldl_test_() -> %% @see foldl/3 %% @see map/2 --spec foldr(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> @@ -1796,8 +1810,8 @@ foldr_test_() -> %% @see foldr/3 %% @see sparse_foldl/3 --spec sparse_foldr(Function, InitialAcc :: A, Array :: array()) -> B when - Function :: fun((Index :: array_indx(), Value :: _, Acc :: A) -> B). +-spec sparse_foldr(Function, InitialAcc :: A, Array :: array(Type)) -> B when + Function :: fun((Index :: array_indx(), Value :: Type, Acc :: A) -> B). sparse_foldr(Function, A, #array{size = N, elements = E, default = D}) when is_function(Function, 3) -> diff --git a/lib/stdlib/src/dict.erl b/lib/stdlib/src/dict.erl index 7e198a2469..6088e1a2dd 100644 --- a/lib/stdlib/src/dict.erl +++ b/lib/stdlib/src/dict.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -41,6 +41,8 @@ -export([store/3,append/3,append_list/3,update/3,update/4,update_counter/3]). -export([fold/3,map/2,filter/2,merge/3]). +-export_type([dict/0, dict/2]). + %% Low-level interface. %%-export([get_slot/2,get_bucket/2,on_bucket/3,fold_dict/3, %% maybe_expand/2,maybe_contract/2]). @@ -53,6 +55,9 @@ -define(exp_size, (?seg_size * ?expand_load)). -define(con_size, (?seg_size * ?contract_load)). +-type segs(K, V) :: tuple() + | {K, V}. % dummy + %% Define a hashtable. The default values are the standard ones. -record(dict, {size=0 :: non_neg_integer(), % Number of elements @@ -62,14 +67,13 @@ exp_size=?exp_size :: non_neg_integer(), % Size to expand at con_size=?con_size :: non_neg_integer(), % Size to contract at empty :: tuple(), % Empty segment - segs :: tuple() % Segments + segs :: segs(_, _) % Segments }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #dict{} -%% structure and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque dict() :: #dict{}. + + +-opaque dict() :: dict(_, _). + +-opaque dict(Key, Value) :: #dict{segs :: segs(Key, Value)}. -define(kv(K,V), [K|V]). % Key-Value pair format %%-define(kv(K,V), {K,V}). % Key-Value pair format @@ -81,8 +85,7 @@ new() -> #dict{empty=Empty,segs={Empty}}. -spec is_key(Key, Dict) -> boolean() when - Key :: term(), - Dict :: dict(). + Dict :: dict(Key, Value :: term()). is_key(Key, D) -> Slot = get_slot(D, Key), @@ -94,15 +97,15 @@ find_key(K, [_|Bkt]) -> find_key(K, Bkt); find_key(_, []) -> false. -spec to_list(Dict) -> List when - Dict :: dict(), - List :: [{Key :: term(), Value :: term()}]. + Dict :: dict(Key, Value), + List :: [{Key, Value}]. to_list(D) -> fold(fun (Key, Val, List) -> [{Key,Val}|List] end, [], D). -spec from_list(List) -> Dict when - List :: [{Key :: term(), Value :: term()}], - Dict :: dict(). + Dict :: dict(Key, Value), + List :: [{Key, Value}]. from_list(L) -> lists:foldl(fun ({K,V}, D) -> store(K, V, D) end, new(), L). @@ -118,9 +121,7 @@ size(#dict{size=N}) when is_integer(N), N >= 0 -> N. is_empty(#dict{size=N}) -> N =:= 0. -spec fetch(Key, Dict) -> Value when - Key :: term(), - Dict :: dict(), - Value :: term(). + Dict :: dict(Key, Value). fetch(Key, D) -> Slot = get_slot(D, Key), @@ -135,9 +136,7 @@ fetch_val(K, [_|Bkt]) -> fetch_val(K, Bkt); fetch_val(_, []) -> throw(badarg). -spec find(Key, Dict) -> {'ok', Value} | 'error' when - Key :: term(), - Dict :: dict(), - Value :: term(). + Dict :: dict(Key, Value). find(Key, D) -> Slot = get_slot(D, Key), @@ -149,16 +148,16 @@ find_val(K, [_|Bkt]) -> find_val(K, Bkt); find_val(_, []) -> error. -spec fetch_keys(Dict) -> Keys when - Dict :: dict(), - Keys :: [term()]. + Dict :: dict(Key, Value :: term()), + Keys :: [Key]. fetch_keys(D) -> fold(fun (Key, _Val, Keys) -> [Key|Keys] end, [], D). -spec erase(Key, Dict1) -> Dict2 when - Key :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). + %% Erase all elements with key Key. erase(Key, D0) -> @@ -174,10 +173,8 @@ erase_key(Key, [E|Bkt0]) -> erase_key(_, []) -> {[],0}. -spec store(Key, Value, Dict1) -> Dict2 when - Key :: term(), - Value :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). store(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -194,10 +191,8 @@ store_bkt_val(Key, New, [Other|Bkt0]) -> store_bkt_val(Key, New, []) -> {[?kv(Key,New)],1}. -spec append(Key, Value, Dict1) -> Dict2 when - Key :: term(), - Value :: term(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). append(Key, Val, D0) -> Slot = get_slot(D0, Key), @@ -214,10 +209,9 @@ append_bkt(Key, Val, [Other|Bkt0]) -> append_bkt(Key, Val, []) -> {[?kv(Key,[Val])],1}. -spec append_list(Key, ValList, Dict1) -> Dict2 when - Key :: term(), - ValList :: [Value :: term()], - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + ValList :: [Value]. append_list(Key, L, D0) -> Slot = get_slot(D0, Key), @@ -288,10 +282,9 @@ app_list_bkt(Key, L, []) -> {[?kv(Key,L)],1}. %% {[Other|Bkt1],Dc}. -spec update(Key, Fun, Dict1) -> Dict2 when - Key :: term(), - Fun :: fun((Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Fun :: fun((Value1 :: Value) -> Value2 :: Value). update(Key, F, D0) -> Slot = get_slot(D0, Key), @@ -311,11 +304,10 @@ update_bkt(_Key, _F, []) -> throw(badarg). -spec update(Key, Fun, Initial, Dict1) -> Dict2 when - Key :: term(), - Initial :: term(), - Fun :: fun((Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Fun :: fun((Value1 :: Value) -> Value2 :: Value), + Initial :: Value. update(Key, F, Init, D0) -> Slot = get_slot(D0, Key), @@ -331,10 +323,9 @@ update_bkt(Key, F, I, [Other|Bkt0]) -> update_bkt(Key, F, I, []) when is_function(F, 1) -> {[?kv(Key,I)],1}. -spec update_counter(Key, Increment, Dict1) -> Dict2 when - Key :: term(), - Increment :: number(), - Dict1 :: dict(), - Dict2 :: dict(). + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value), + Increment :: number(). update_counter(Key, Incr, D0) when is_number(Incr) -> Slot = get_slot(D0, Key), @@ -351,36 +342,35 @@ counter_bkt(Key, I, []) -> {[?kv(Key,I)],1}. -spec fold(Fun, Acc0, Dict) -> Acc1 when Fun :: fun((Key, Value, AccIn) -> AccOut), - Key :: term(), - Value :: term(), - Acc0 :: term(), - Acc1 :: term(), - AccIn :: term(), - AccOut :: term(), - Dict :: dict(). + Dict :: dict(Key, Value), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc. + %% Fold function Fun over all "bags" in Table and return Accumulator. fold(F, Acc, D) -> fold_dict(F, Acc, D). -spec map(Fun, Dict1) -> Dict2 when - Fun :: fun((Key :: term(), Value1 :: term()) -> Value2 :: term()), - Dict1 :: dict(), - Dict2 :: dict(). + Fun :: fun((Key, Value1) -> Value2), + Dict1 :: dict(Key, Value1), + Dict2 :: dict(Key, Value2). map(F, D) -> map_dict(F, D). -spec filter(Pred, Dict1) -> Dict2 when - Pred :: fun((Key :: term(), Value :: term()) -> boolean()), - Dict1 :: dict(), - Dict2 :: dict(). + Pred :: fun((Key , Value) -> boolean()), + Dict1 :: dict(Key, Value), + Dict2 :: dict(Key, Value). filter(F, D) -> filter_dict(F, D). -spec merge(Fun, Dict1, Dict2) -> Dict3 when - Fun :: fun((Key :: term(), Value1 :: term(), Value2 :: term()) -> Value :: term()), - Dict1 :: dict(), - Dict2 :: dict(), - Dict3 :: dict(). + Fun :: fun((Key, Value1, Value2) -> Value), + Dict1 :: dict(Key, Value1), + Dict2 :: dict(Key, Value2), + Dict3 :: dict(Key, Value). merge(F, D1, D2) when D1#dict.size < D2#dict.size -> fold_dict(fun (K, V1, D) -> diff --git a/lib/stdlib/src/digraph.erl b/lib/stdlib/src/digraph.erl index 78f74631dc..0c21271529 100644 --- a/lib/stdlib/src/digraph.erl +++ b/lib/stdlib/src/digraph.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,18 +36,14 @@ -export([get_short_path/3, get_short_cycle/2]). --export_type([digraph/0, d_type/0, vertex/0, edge/0]). +-export_type([graph/0, d_type/0, vertex/0, edge/0]). -record(digraph, {vtab = notable :: ets:tab(), etab = notable :: ets:tab(), ntab = notable :: ets:tab(), cyclic = true :: boolean()}). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #digraph{} -%% record and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque digraph() :: #digraph{}. + +-opaque graph() :: #digraph{}. -type edge() :: term(). -type label() :: term(). @@ -67,11 +63,11 @@ -type d_cyclicity() :: 'acyclic' | 'cyclic'. -type d_type() :: d_cyclicity() | d_protection(). --spec new() -> digraph(). +-spec new() -> graph(). new() -> new([]). --spec new(Type) -> digraph() when +-spec new(Type) -> graph() when Type :: [d_type()]. new(Type) -> @@ -106,7 +102,7 @@ check_type(_, _, _) -> error. %% %% Set graph type %% --spec set_type([{'cyclic', boolean()}], digraph()) -> digraph(). +-spec set_type([{'cyclic', boolean()}], graph()) -> graph(). set_type([{cyclic,V} | Ks], G) -> set_type(Ks, G#digraph{cyclic = V}); @@ -116,7 +112,7 @@ set_type([], G) -> G. %% Data access functions -spec delete(G) -> 'true' when - G :: digraph(). + G :: graph(). delete(G) -> ets:delete(G#digraph.vtab), @@ -124,7 +120,7 @@ delete(G) -> ets:delete(G#digraph.ntab). -spec info(G) -> InfoList when - G :: digraph(), + G :: graph(), InfoList :: [{'cyclicity', Cyclicity :: d_cyclicity()} | {'memory', NoWords :: non_neg_integer()} | {'protection', Protection :: d_protection()}]. @@ -142,20 +138,20 @@ info(G) -> [{cyclicity, Cyclicity}, {memory, Memory}, {protection, Protection}]. -spec add_vertex(G) -> vertex() when - G :: digraph(). + G :: graph(). add_vertex(G) -> do_add_vertex({new_vertex_id(G), []}, G). -spec add_vertex(G, V) -> vertex() when - G :: digraph(), + G :: graph(), V :: vertex(). add_vertex(G, V) -> do_add_vertex({V, []}, G). -spec add_vertex(G, V, Label) -> vertex() when - G :: digraph(), + G :: graph(), V :: vertex(), Label :: label(). @@ -163,21 +159,21 @@ add_vertex(G, V, D) -> do_add_vertex({V, D}, G). -spec del_vertex(G, V) -> 'true' when - G :: digraph(), + G :: graph(), V :: vertex(). del_vertex(G, V) -> do_del_vertex(V, G). -spec del_vertices(G, Vertices) -> 'true' when - G :: digraph(), + G :: graph(), Vertices :: [vertex()]. del_vertices(G, Vs) -> do_del_vertices(Vs, G). -spec vertex(G, V) -> {V, Label} | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Label :: label(). @@ -188,37 +184,37 @@ vertex(G, V) -> end. -spec no_vertices(G) -> non_neg_integer() when - G :: digraph(). + G :: graph(). no_vertices(G) -> ets:info(G#digraph.vtab, size). -spec vertices(G) -> Vertices when - G :: digraph(), + G :: graph(), Vertices :: [vertex()]. vertices(G) -> ets:select(G#digraph.vtab, [{{'$1', '_'}, [], ['$1']}]). --spec source_vertices(digraph()) -> [vertex()]. +-spec source_vertices(graph()) -> [vertex()]. source_vertices(G) -> collect_vertices(G, in). --spec sink_vertices(digraph()) -> [vertex()]. +-spec sink_vertices(graph()) -> [vertex()]. sink_vertices(G) -> collect_vertices(G, out). -spec in_degree(G, V) -> non_neg_integer() when - G :: digraph(), + G :: graph(), V :: vertex(). in_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {in, V})). -spec in_neighbours(G, V) -> Vertex when - G :: digraph(), + G :: graph(), V :: vertex(), Vertex :: [vertex()]. @@ -228,7 +224,7 @@ in_neighbours(G, V) -> collect_elems(ets:lookup(NT, {in, V}), ET, 2). -spec in_edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -236,14 +232,14 @@ in_edges(G, V) -> ets:select(G#digraph.ntab, [{{{in, V}, '$1'}, [], ['$1']}]). -spec out_degree(G, V) -> non_neg_integer() when - G :: digraph(), + G :: graph(), V :: vertex(). out_degree(G, V) -> length(ets:lookup(G#digraph.ntab, {out, V})). -spec out_neighbours(G, V) -> Vertices when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex()]. @@ -253,7 +249,7 @@ out_neighbours(G, V) -> collect_elems(ets:lookup(NT, {out, V}), ET, 3). -spec out_edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -261,7 +257,7 @@ out_edges(G, V) -> ets:select(G#digraph.ntab, [{{{out, V}, '$1'}, [], ['$1']}]). -spec add_edge(G, V1, V2) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(). @@ -269,7 +265,7 @@ add_edge(G, V1, V2) -> do_add_edge({new_edge_id(G), V1, V2, []}, G). -spec add_edge(G, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Label :: label(). @@ -278,7 +274,7 @@ add_edge(G, V1, V2, D) -> do_add_edge({new_edge_id(G), V1, V2, D}, G). -spec add_edge(G, E, V1, V2, Label) -> edge() | {'error', add_edge_err_rsn()} when - G :: digraph(), + G :: graph(), E :: edge(), V1 :: vertex(), V2 :: vertex(), @@ -288,34 +284,34 @@ add_edge(G, E, V1, V2, D) -> do_add_edge({E, V1, V2, D}, G). -spec del_edge(G, E) -> 'true' when - G :: digraph(), + G :: graph(), E :: edge(). del_edge(G, E) -> do_del_edges([E], G). -spec del_edges(G, Edges) -> 'true' when - G :: digraph(), + G :: graph(), Edges :: [edge()]. del_edges(G, Es) -> do_del_edges(Es, G). -spec no_edges(G) -> non_neg_integer() when - G :: digraph(). + G :: graph(). no_edges(G) -> ets:info(G#digraph.etab, size). -spec edges(G) -> Edges when - G :: digraph(), + G :: graph(), Edges :: [edge()]. edges(G) -> ets:select(G#digraph.etab, [{{'$1', '_', '_', '_'}, [], ['$1']}]). -spec edges(G, V) -> Edges when - G :: digraph(), + G :: graph(), V :: vertex(), Edges :: [edge()]. @@ -324,7 +320,7 @@ edges(G, V) -> {{{in, V}, '$1'}, [], ['$1']}]). -spec edge(G, E) -> {E, V1, V2, Label} | 'false' when - G :: digraph(), + G :: graph(), E :: edge(), V1 :: vertex(), V2 :: vertex(), @@ -339,7 +335,7 @@ edge(G, E) -> %% %% Generate a "unique" edge identifier (relative to this graph) %% --spec new_edge_id(digraph()) -> edge(). +-spec new_edge_id(graph()) -> edge(). new_edge_id(G) -> NT = G#digraph.ntab, @@ -351,7 +347,7 @@ new_edge_id(G) -> %% %% Generate a "unique" vertex identifier (relative to this graph) %% --spec new_vertex_id(digraph()) -> vertex(). +-spec new_vertex_id(graph()) -> vertex(). new_vertex_id(G) -> NT = G#digraph.ntab, @@ -371,7 +367,7 @@ collect_elems([{_,Key}|Keys], Table, Index, Acc) -> [ets:lookup_element(Table, Key, Index)|Acc]); collect_elems([], _, _, Acc) -> Acc. --spec do_add_vertex({vertex(), label()}, digraph()) -> vertex(). +-spec do_add_vertex({vertex(), label()}, graph()) -> vertex(). do_add_vertex({V, _Label} = VL, G) -> ets:insert(G#digraph.vtab, VL), @@ -430,14 +426,14 @@ do_del_edge(E, V1, V2, G) -> {{{out,V1}, E}, [], [true]}]), ets:delete(G#digraph.etab, E). --spec rm_edges([vertex(),...], digraph()) -> 'true'. +-spec rm_edges([vertex(),...], graph()) -> 'true'. rm_edges([V1, V2|Vs], G) -> rm_edge(V1, V2, G), rm_edges([V2|Vs], G); rm_edges(_, _) -> true. --spec rm_edge(vertex(), vertex(), digraph()) -> 'ok'. +-spec rm_edge(vertex(), vertex(), graph()) -> 'ok'. rm_edge(V1, V2, G) -> Es = out_edges(G, V1), @@ -456,7 +452,7 @@ rm_edge_0([], _, _, #digraph{}) -> ok. %% %% Check that endpoints exist %% --spec do_add_edge({edge(), vertex(), vertex(), label()}, digraph()) -> +-spec do_add_edge({edge(), vertex(), vertex(), label()}, graph()) -> edge() | {'error', add_edge_err_rsn()}. do_add_edge({E, V1, V2, Label}, G) -> @@ -484,14 +480,14 @@ other_edge_exists(#digraph{etab = ET}, E, V1, V2) -> false end. --spec do_insert_edge(edge(), vertex(), vertex(), label(), digraph()) -> edge(). +-spec do_insert_edge(edge(), vertex(), vertex(), label(), graph()) -> edge(). do_insert_edge(E, V1, V2, Label, #digraph{ntab=NT, etab=ET}) -> ets:insert(NT, [{{out, V1}, E}, {{in, V2}, E}]), ets:insert(ET, {E, V1, V2, Label}), E. --spec acyclic_add_edge(edge(), vertex(), vertex(), label(), digraph()) -> +-spec acyclic_add_edge(edge(), vertex(), vertex(), label(), graph()) -> edge() | {'error', {'bad_edge', [vertex()]}}. acyclic_add_edge(_E, V1, V2, _L, _G) when V1 =:= V2 -> @@ -507,7 +503,7 @@ acyclic_add_edge(E, V1, V2, Label, G) -> %% -spec del_path(G, V1, V2) -> 'true' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(). @@ -529,7 +525,7 @@ del_path(G, V1, V2) -> %% -spec get_cycle(G, V) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex(),...]. @@ -550,7 +546,7 @@ get_cycle(G, V) -> %% -spec get_path(G, V1, V2) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Vertices :: [vertex(),...]. @@ -589,7 +585,7 @@ one_path([], _, [], _, _, _, _, _Counter) -> false. %% -spec get_short_cycle(G, V) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V :: vertex(), Vertices :: [vertex(),...]. @@ -602,7 +598,7 @@ get_short_cycle(G, V) -> %% -spec get_short_path(G, V1, V2) -> Vertices | 'false' when - G :: digraph(), + G :: graph(), V1 :: vertex(), V2 :: vertex(), Vertices :: [vertex(),...]. diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl index 0e248df453..011bcd0260 100644 --- a/lib/stdlib/src/digraph_utils.erl +++ b/lib/stdlib/src/digraph_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -43,28 +43,28 @@ %% -spec components(Digraph) -> [Component] when - Digraph :: digraph(), + Digraph :: digraph:graph(), Component :: [digraph:vertex()]. components(G) -> forest(G, fun inout/3). -spec strong_components(Digraph) -> [StrongComponent] when - Digraph :: digraph(), + Digraph :: digraph:graph(), StrongComponent :: [digraph:vertex()]. strong_components(G) -> forest(G, fun in/3, revpostorder(G)). -spec cyclic_strong_components(Digraph) -> [StrongComponent] when - Digraph :: digraph(), + Digraph :: digraph:graph(), StrongComponent :: [digraph:vertex()]. cyclic_strong_components(G) -> remove_singletons(strong_components(G), G, []). -spec reachable(Vertices, Digraph) -> Reachable when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reachable :: [digraph:vertex()]. @@ -72,7 +72,7 @@ reachable(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, first)). -spec reachable_neighbours(Vertices, Digraph) -> Reachable when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reachable :: [digraph:vertex()]. @@ -80,7 +80,7 @@ reachable_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun out/3, Vs, not_first)). -spec reaching(Vertices, Digraph) -> Reaching when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reaching :: [digraph:vertex()]. @@ -88,7 +88,7 @@ reaching(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, first)). -spec reaching_neighbours(Vertices, Digraph) -> Reaching when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], Reaching :: [digraph:vertex()]. @@ -96,7 +96,7 @@ reaching_neighbours(Vs, G) when is_list(Vs) -> lists:append(forest(G, fun in/3, Vs, not_first)). -spec topsort(Digraph) -> Vertices | 'false' when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. topsort(G) -> @@ -107,13 +107,13 @@ topsort(G) -> end. -spec is_acyclic(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_acyclic(G) -> loop_vertices(G) =:= [] andalso topsort(G) =/= false. -spec arborescence_root(Digraph) -> 'no' | {'yes', Root} when - Digraph :: digraph(), + Digraph :: digraph:graph(), Root :: digraph:vertex(). arborescence_root(G) -> @@ -136,29 +136,29 @@ arborescence_root(G) -> end. -spec is_arborescence(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_arborescence(G) -> arborescence_root(G) =/= no. -spec is_tree(Digraph) -> boolean() when - Digraph :: digraph(). + Digraph :: digraph:graph(). is_tree(G) -> (digraph:no_edges(G) =:= digraph:no_vertices(G) - 1) andalso (length(components(G)) =:= 1). -spec loop_vertices(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. loop_vertices(G) -> [V || V <- digraph:vertices(G), is_reflexive_vertex(V, G)]. -spec subgraph(Digraph, Vertices) -> SubGraph when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()], - SubGraph :: digraph(). + SubGraph :: digraph:graph(). subgraph(G, Vs) -> try @@ -169,8 +169,8 @@ subgraph(G, Vs) -> end. -spec subgraph(Digraph, Vertices, Options) -> SubGraph when - Digraph :: digraph(), - SubGraph :: digraph(), + Digraph :: digraph:graph(), + SubGraph :: digraph:graph(), Vertices :: [digraph:vertex()], Options :: [{'type', SubgraphType} | {'keep_labels', boolean()}], SubgraphType :: 'inherit' | [digraph:d_type()]. @@ -184,8 +184,8 @@ subgraph(G, Vs, Opts) -> end. -spec condensation(Digraph) -> CondensedDigraph when - Digraph :: digraph(), - CondensedDigraph :: digraph(). + Digraph :: digraph:graph(), + CondensedDigraph :: digraph:graph(). condensation(G) -> SCs = strong_components(G), @@ -209,14 +209,14 @@ condensation(G) -> SCG. -spec preorder(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. preorder(G) -> lists:reverse(revpreorder(G)). -spec postorder(Digraph) -> Vertices when - Digraph :: digraph(), + Digraph :: digraph:graph(), Vertices :: [digraph:vertex()]. postorder(G) -> diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index dc25b6b9f4..68e079b7e5 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -46,8 +46,8 @@ istk=[], %Ifdef stack sstk=[], %State stack path=[], %Include-path - macs = dict:new() :: dict(), %Macros (don't care locations) - uses = dict:new() :: dict(), %Macro use structure + macs = dict:new() :: dict:dict(),%Macros (don't care locations) + uses = dict:new() :: dict:dict(),%Macro use structure pre_opened = false :: boolean() }). diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 0c6f41f594..9f5be2da37 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -85,8 +85,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> -record(usage, { calls = dict:new(), %Who calls who imported = [], %Actually imported functions - used_records=sets:new() :: set(), %Used record definitions - used_types = dict:new() :: dict() %Used type definitions + used_records=sets:new() :: sets:set(),%Used record definitions + used_types = dict:new() :: dict:dict()%Used type definitions }). %% Define the lint state record. @@ -95,13 +95,13 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> -record(lint, {state=start :: 'start' | 'attribute' | 'function', module=[], %Module behaviour=[], %Behaviour - exports=gb_sets:empty() :: gb_set(), %Exports + exports=gb_sets:empty() :: gb_sets:set(),%Exports imports=[], %Imports compile=[], %Compile flags - records=dict:new() :: dict(), %Record definitions - locals=gb_sets:empty() :: gb_set(), %All defined functions (prescanned) - no_auto=gb_sets:empty() :: gb_set() | 'all', %Functions explicitly not autoimported - defined=gb_sets:empty() :: gb_set(), %Defined fuctions + records=dict:new() :: dict:dict(), %Record definitions + locals=gb_sets:empty() :: gb_sets:set(),%All defined functions (prescanned) + no_auto=gb_sets:empty() :: gb_sets:set() | 'all',%Functions explicitly not autoimported + defined=gb_sets:empty() :: gb_sets:set(),%Defined fuctions on_load=[] :: [fa()], %On-load function on_load_line=0 :: line(), %Line for on_load clashes=[], %Exported functions named as BIFs @@ -118,10 +118,10 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> new = false :: boolean(), %Has user-defined 'new/N' called= [] :: [{fa(),line()}], %Called functions usage = #usage{} :: #usage{}, - specs = dict:new() :: dict(), %Type specifications - callbacks = dict:new() :: dict(), %Callback types - types = dict:new() :: dict(), %Type definitions - exp_types=gb_sets:empty():: gb_set() %Exported types + specs = dict:new() :: dict:dict(), %Type specifications + callbacks = dict:new() :: dict:dict(), %Callback types + types = dict:new() :: dict:dict(), %Type definitions + exp_types=gb_sets:empty():: gb_sets:set()%Exported types }). -type lint_state() :: #lint{}. @@ -344,9 +344,10 @@ format_error(spec_wrong_arity) -> "spec has the wrong arity"; format_error(callback_wrong_arity) -> "callback has the wrong arity"; -format_error({imported_predefined_type, Name}) -> - io_lib:format("referring to built-in type ~w as a remote type; " - "please take out the module name", [Name]); +format_error({deprecated_type, {Name, Arity}, {Mod, NewName}, Rel}) -> + io_lib:format("type ~w/~w is deprecated and will be " + "removed in ~s; use ~w:~w/~w", + [Name, Arity, Rel, Mod, NewName, Arity]); format_error({not_exported_opaque, {TypeName, Arity}}) -> io_lib:format("opaque type ~w~s is not exported", [TypeName, gen_type_paren(Arity)]); @@ -1155,7 +1156,7 @@ export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) -> add_error(Line, {bad_export_type, ETs}, St0) end. --spec exports(lint_state()) -> gb_set(). +-spec exports(lint_state()) -> gb_sets:set(). exports(#lint{compile = Opts, defined = Defs, exports = Es}) -> case lists:member(export_all, Opts) of @@ -1888,7 +1889,7 @@ is_guard_test(Expression, Forms) -> end, start(), RecordAttributes), is_guard_test2(zip_file_and_line(Expression, "nofile"), St0#lint.records). -%% is_guard_test2(Expression, RecordDefs :: dict()) -> boolean(). +%% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean(). is_guard_test2({call,Line,{atom,Lr,record},[E,A]}, RDs) -> is_gexpr({call,Line,{atom,Lr,is_record},[E,A]}, RDs); is_guard_test2({call,_Line,{atom,_La,Test},As}=Call, RDs) -> @@ -2566,18 +2567,12 @@ check_type({paren_type, _L, [Type]}, SeenVars, St) -> check_type(Type, SeenVars, St); check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]}, SeenVars, #lint{module=CurrentMod} = St) -> - St1 = - case is_default_type({Name, length(Args)}) - orelse is_var_arity_type(Name) of - true -> add_error(L, {imported_predefined_type, Name}, St); - false -> St - end, case Mod =:= CurrentMod of - true -> check_type({type, L, Name, Args}, SeenVars, St1); + true -> check_type({type, L, Name, Args}, SeenVars, St); false -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) - end, {SeenVars, St1}, Args) + end, {SeenVars, St}, Args) end; check_type({integer, _L, _}, SeenVars, St) -> {SeenVars, St}; check_type({atom, _L, _}, SeenVars, St) -> {SeenVars, St}; @@ -2635,14 +2630,33 @@ check_type({type, _L, product, Args}, SeenVars, St) -> lists:foldl(fun(T, {AccSeenVars, AccSt}) -> check_type(T, AccSeenVars, AccSt) end, {SeenVars, St}, Args); -check_type({type, La, TypeName, Args}, SeenVars, #lint{usage=Usage} = St) -> +check_type({type, La, TypeName, Args}, SeenVars, St) -> + #lint{usage=Usage, module = Module, types=Types} = St, Arity = length(Args), + TypePair = {TypeName, Arity}, St1 = case is_var_arity_type(TypeName) of true -> St; false -> - OldUsed = Usage#usage.used_types, - UsedTypes = dict:store({TypeName, Arity}, La, OldUsed), - St#lint{usage=Usage#usage{used_types=UsedTypes}} + Obsolete = obsolete_type(TypePair), + IsObsolete = + case Obsolete of + {deprecated, {M, _}, _} when M =/= Module -> + case dict:find(TypePair, Types) of + {ok, _} -> false; + error -> true + end; + _ -> false + end, + case IsObsolete of + true -> + {deprecated, Replacement, Rel} = Obsolete, + W = {deprecated_type, TypePair, Replacement, Rel}, + add_warning(La, W, St); + false -> + OldUsed = Usage#usage.used_types, + UsedTypes = dict:store(TypePair, La, OldUsed), + St#lint{usage=Usage#usage{used_types=UsedTypes}} + end end, check_type({type, -1, product, Args}, SeenVars, St1); check_type(I, SeenVars, St) -> @@ -2765,6 +2779,17 @@ is_newly_introduced_builtin_type({set, 0}) -> true; % opaque is_newly_introduced_builtin_type({boolean, 0}) -> true; is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. +%% Obsolete in OTP 17.0. +obsolete_type({array, 0}) -> {deprecated, {array, array}, "OTP 18.0"}; +obsolete_type({dict, 0}) -> {deprecated, {dict, dict}, "OTP 18.0"}; +obsolete_type({digraph, 0}) -> {deprecated, {digraph, graph}, "OTP 18.0"}; +obsolete_type({gb_set, 0}) -> {deprecated, {gb_sets, set}, "OTP 18.0"}; +obsolete_type({gb_tree, 0}) -> {deprecated, {gb_trees, tree}, "OTP 18.0"}; +obsolete_type({queue, 0}) -> {deprecated, {queue, queue}, "OTP 18.0"}; +obsolete_type({set, 0}) -> {deprecated, {sets, set}, "OTP 18.0"}; +obsolete_type({tid, 0}) -> {deprecated, {ets, tid}, "OTP 18.0"}; +obsolete_type({Name, _}) when is_atom(Name) -> no. + %% spec_decl(Line, Fun, Types, State) -> State. spec_decl(Line, MFA0, TypeSpecs, St0 = #lint{specs = Specs, module = Mod}) -> diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index cc5e69f574..42b11a97e2 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -53,10 +53,8 @@ | {tab(),integer(),integer(),binary(),list(),integer()} | {tab(),_,_,integer(),binary(),list(),integer(),integer()}. -%% a similar definition is also in erl_types -opaque tid() :: integer(). -%% these ones are also defined in erl_bif_types -type match_pattern() :: atom() | tuple(). -type match_spec() :: [{match_pattern(), [_], [_]}]. diff --git a/lib/stdlib/src/gb_sets.erl b/lib/stdlib/src/gb_sets.erl index 237317ac94..0a26d0182d 100644 --- a/lib/stdlib/src/gb_sets.erl +++ b/lib/stdlib/src/gb_sets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -196,31 +196,32 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Some types. --export_type([iter/0]). +-export_type([set/0, set/1, iter/0, iter/1]). --type gb_set_node() :: 'nil' | {term(), _, _}. +-type gb_set_node(Element) :: 'nil' | {Element, _, _}. +-type gb_set_node() :: gb_set_node(_). +-opaque set(Element) :: {non_neg_integer(), gb_set_node(Element)}. +-opaque set() :: set(_). +-opaque iter(Element) :: [gb_set_node(Element)]. -opaque iter() :: [gb_set_node()]. -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque gb_set() :: {non_neg_integer(), gb_set_node()}. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% gb_sets:set() in OTP 17 only. + -spec empty() -> Set when - Set :: gb_set(). + Set :: gb_sets:set(). empty() -> {0, nil}. -spec new() -> Set when - Set :: gb_set(). + Set :: gb_sets:set(). new() -> empty(). -spec is_empty(Set) -> boolean() when - Set :: gb_set(). + Set :: gb_sets:set(). is_empty({0, nil}) -> true; @@ -228,27 +229,24 @@ is_empty(_) -> false. -spec size(Set) -> non_neg_integer() when - Set :: gb_set(). + Set :: gb_sets:set(). size({Size, _}) -> Size. --spec singleton(Element) -> gb_set() when - Element :: term(). +-spec singleton(Element) -> set(Element). singleton(Key) -> {1, {Key, nil, nil}}. -spec is_element(Element, Set) -> boolean() when - Element :: term(), - Set :: gb_set(). + Set :: set(Element). is_element(Key, S) -> is_member(Key, S). -spec is_member(Element, Set) -> boolean() when - Element :: term(), - Set :: gb_set(). + Set :: set(Element). is_member(Key, {_, T}) -> is_member_1(Key, T). @@ -263,9 +261,8 @@ is_member_1(_, nil) -> false. -spec insert(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). insert(Key, {S, T}) -> S1 = S + 1, @@ -322,8 +319,8 @@ count(nil) -> {1, 0}. -spec balance(Set1) -> Set2 when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). balance({S, T}) -> {S, balance(T, S)}. @@ -349,17 +346,15 @@ balance_list_1(L, 0) -> {nil, L}. -spec add_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). add_element(X, S) -> add(X, S). -spec add(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). add(X, S) -> case is_member(X, S) of @@ -370,32 +365,30 @@ add(X, S) -> end. -spec from_list(List) -> Set when - List :: [term()], - Set :: gb_set(). + List :: [Element], + Set :: set(Element). from_list(L) -> from_ordset(ordsets:from_list(L)). -spec from_ordset(List) -> Set when - List :: [term()], - Set :: gb_set(). + List :: [Element], + Set :: set(Element). from_ordset(L) -> S = length(L), {S, balance_list(L, S)}. -spec del_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). del_element(Key, S) -> delete_any(Key, S). -spec delete_any(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). delete_any(Key, S) -> case is_member(Key, S) of @@ -406,9 +399,8 @@ delete_any(Key, S) -> end. -spec delete(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). delete(Key, {S, T}) -> {S - 1, delete_1(Key, T)}. @@ -431,9 +423,8 @@ merge(Smaller, Larger) -> {Key, Smaller, Larger1}. -spec take_smallest(Set1) -> {Element, Set2} when - Set1 :: gb_set(), - Set2 :: gb_set(), - Element :: term(). + Set1 :: set(Element), + Set2 :: set(Element). take_smallest({S, T}) -> {Key, Larger} = take_smallest1(T), @@ -445,8 +436,8 @@ take_smallest1({Key, Smaller, Larger}) -> {Key1, Smaller1} = take_smallest1(Smaller), {Key1, {Key, Smaller1, Larger}}. --spec smallest(Set) -> term() when - Set :: gb_set(). +-spec smallest(Set) -> Element when + Set :: set(Element). smallest({_, T}) -> smallest_1(T). @@ -457,9 +448,8 @@ smallest_1({_Key, Smaller, _Larger}) -> smallest_1(Smaller). -spec take_largest(Set1) -> {Element, Set2} when - Set1 :: gb_set(), - Set2 :: gb_set(), - Element :: term(). + Set1 :: set(Element), + Set2 :: set(Element). take_largest({S, T}) -> {Key, Smaller} = take_largest1(T), @@ -471,8 +461,8 @@ take_largest1({Key, Smaller, Larger}) -> {Key1, Larger1} = take_largest1(Larger), {Key1, {Key, Smaller, Larger1}}. --spec largest(Set) -> term() when - Set :: gb_set(). +-spec largest(Set) -> Element when + Set :: set(Element). largest({_, T}) -> largest_1(T). @@ -483,8 +473,8 @@ largest_1({_Key, _Smaller, Larger}) -> largest_1(Larger). -spec to_list(Set) -> List when - Set :: gb_set(), - List :: [term()]. + Set :: set(Element), + List :: [Element]. to_list({_, T}) -> to_list(T, []). @@ -496,8 +486,8 @@ to_list({Key, Small, Big}, L) -> to_list(nil, L) -> L. -spec iterator(Set) -> Iter when - Set :: gb_set(), - Iter :: iter(). + Set :: set(Element), + Iter :: iter(Element). iterator({_, T}) -> iterator(T, []). @@ -513,9 +503,8 @@ iterator(nil, As) -> As. -spec next(Iter1) -> {Element, Iter2} | 'none' when - Iter1 :: iter(), - Iter2 :: iter(), - Element :: term(). + Iter1 :: iter(Element), + Iter2 :: iter(Element). next([{X, _, T} | As]) -> {X, iterator(T, As)}; @@ -546,9 +535,9 @@ next([]) -> %% overhead. -spec union(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). union({N1, T1}, {N2, T2}) when N2 < N1 -> union(to_list_1(T2), N2, T1, N1); @@ -570,7 +559,7 @@ union(L, N1, T2, N2) -> union_1(L, mk_set(N2, T2)) end. --spec mk_set(non_neg_integer(), gb_set_node()) -> gb_set(). +-spec mk_set(non_neg_integer(), gb_set_node(T)) -> set(T). mk_set(N, T) -> {N, T}. @@ -651,8 +640,8 @@ balance_revlist_1(L, 0) -> {nil, L}. -spec union(SetList) -> Set when - SetList :: [gb_set(),...], - Set :: gb_set(). + SetList :: [set(Element),...], + Set :: set(Element). union([S | Ss]) -> union_list(S, Ss); @@ -666,9 +655,9 @@ union_list(S, []) -> S. %% The rest is modelled on the above. -spec intersection(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). intersection({N1, T1}, {N2, T2}) when N2 < N1 -> intersection(to_list_1(T2), N2, T1, N1); @@ -717,8 +706,8 @@ intersection_2(_, [], As, S) -> {S, balance_revlist(As, S)}. -spec intersection(SetList) -> Set when - SetList :: [gb_set(),...], - Set :: gb_set(). + SetList :: [set(Element),...], + Set :: set(Element). intersection([S | Ss]) -> intersection_list(S, Ss). @@ -728,8 +717,8 @@ intersection_list(S, [S1 | Ss]) -> intersection_list(S, []) -> S. -spec is_disjoint(Set1, Set2) -> boolean() when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). is_disjoint({N1, T1}, {N2, T2}) when N1 < N2 -> is_disjoint_1(T1, T2); @@ -758,17 +747,17 @@ is_disjoint_1(_, nil) -> %% traverse the whole element list of the left operand. -spec subtract(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). subtract(S1, S2) -> difference(S1, S2). -spec difference(Set1, Set2) -> Set3 when - Set1 :: gb_set(), - Set2 :: gb_set(), - Set3 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). difference({N1, T1}, {N2, T2}) -> difference(to_list_1(T1), N1, T2, N2). @@ -817,8 +806,8 @@ difference_2(Xs, [], As, S) -> %% without the construction of a new set. -spec is_subset(Set1, Set2) -> boolean() when - Set1 :: gb_set(), - Set2 :: gb_set(). + Set1 :: set(Element), + Set2 :: set(Element). is_subset({N1, T1}, {N2, T2}) -> is_subset(to_list_1(T1), N1, T2, N2). @@ -867,20 +856,20 @@ is_set({N, {_, _, _}}) when is_integer(N), N >= 0 -> true; is_set(_) -> false. -spec filter(Pred, Set1) -> Set2 when - Pred :: fun((E :: term()) -> boolean()), - Set1 :: gb_set(), - Set2 :: gb_set(). + Pred :: fun((Element) -> boolean()), + Set1 :: set(Element), + Set2 :: set(Element). filter(F, S) -> from_ordset([X || X <- to_list(S), F(X)]). -spec fold(Function, Acc0, Set) -> Acc1 when - Function :: fun((E :: term(), AccIn) -> AccOut), - Acc0 :: term(), - Acc1 :: term(), - AccIn :: term(), - AccOut :: term(), - Set :: gb_set(). + Function :: fun((Element, AccIn) -> AccOut), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc, + Set :: set(Element). fold(F, A, {_, T}) when is_function(F, 2) -> fold_1(F, A, T). diff --git a/lib/stdlib/src/gb_trees.erl b/lib/stdlib/src/gb_trees.erl index 7a4dfe1a0b..7069b61873 100644 --- a/lib/stdlib/src/gb_trees.erl +++ b/lib/stdlib/src/gb_trees.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -152,25 +152,25 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Some types. --export_type([iter/0]). +-export_type([tree/0, tree/2, iter/0, iter/2]). --type gb_tree_node() :: 'nil' | {_, _, _, _}. +-type gb_tree_node(K, V) :: 'nil' + | {K, V, gb_tree_node(K, V), gb_tree_node(K, V)}. +-type gb_tree_node() :: gb_tree_node(_, _). +-opaque tree(Key, Value) :: {non_neg_integer(), gb_tree_node(Key, Value)}. +-opaque tree() :: tree(_, _). +-opaque iter(Key, Value) :: [gb_tree_node(Key, Value)]. -opaque iter() :: [gb_tree_node()]. -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque gb_tree() :: {non_neg_integer(), gb_tree_node()}. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec empty() -> gb_tree(). +-spec empty() -> tree(). empty() -> {0, nil}. -spec is_empty(Tree) -> boolean() when - Tree :: gb_tree(). + Tree :: tree(). is_empty({0, nil}) -> true; @@ -178,17 +178,15 @@ is_empty(_) -> false. -spec size(Tree) -> non_neg_integer() when - Tree :: gb_tree(). + Tree :: tree(). size({Size, _}) when is_integer(Size), Size >= 0 -> Size. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec lookup(Key, Tree) -> 'none' | {'value', Val} when - Key :: term(), - Val :: term(), - Tree :: gb_tree(). +-spec lookup(Key, Tree) -> 'none' | {'value', Value} when + Tree :: tree(Key, Value). lookup(Key, {_, T}) -> lookup_1(Key, T). @@ -214,8 +212,7 @@ lookup_1(_, nil) -> %% This is a specialized version of `lookup'. -spec is_defined(Key, Tree) -> boolean() when - Key :: term(), - Tree :: gb_tree(). + Tree :: tree(Key, Value :: term()). is_defined(Key, {_, T}) -> is_defined_1(Key, T). @@ -233,10 +230,8 @@ is_defined_1(_, nil) -> %% This is a specialized version of `lookup'. --spec get(Key, Tree) -> Val when - Key :: term(), - Tree :: gb_tree(), - Val :: term(). +-spec get(Key, Tree) -> Value when + Tree :: tree(Key, Value). get(Key, {_, T}) -> get_1(Key, T). @@ -250,11 +245,9 @@ get_1(_, {_, Value, _, _}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec update(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec update(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). update(Key, Val, {S, T}) -> T1 = update_1(Key, Val, T), @@ -271,11 +264,9 @@ update_1(Key, Value, {_, _, Smaller, Bigger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec insert(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec insert(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). insert(Key, Val, {S, T}) when is_integer(S) -> S1 = S+1, @@ -324,11 +315,9 @@ insert_1(Key, _, _, _) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec enter(Key, Val, Tree1) -> Tree2 when - Key :: term(), - Val :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). +-spec enter(Key, Value, Tree1) -> Tree2 when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). enter(Key, Val, T) -> case is_defined(Key, T) of @@ -352,8 +341,8 @@ count(nil) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec balance(Tree1) -> Tree2 when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). balance({S, T}) -> {S, balance(T, S)}. @@ -379,8 +368,8 @@ balance_list_1(L, 0) -> {nil, L}. -spec from_orddict(List) -> Tree when - List :: [{Key :: term(), Val :: term()}], - Tree :: gb_tree(). + List :: [{Key, Value}], + Tree :: tree(Key, Value). from_orddict(L) -> S = length(L), @@ -389,9 +378,8 @@ from_orddict(L) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec delete_any(Key, Tree1) -> Tree2 when - Key :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). delete_any(Key, T) -> case is_defined(Key, T) of @@ -404,9 +392,8 @@ delete_any(Key, T) -> %%% delete. Assumes that key is present. -spec delete(Key, Tree1) -> Tree2 when - Key :: term(), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). delete(Key, {S, T}) when is_integer(S), S >= 0 -> {S - 1, delete_1(Key, T)}. @@ -432,11 +419,9 @@ merge(Smaller, Larger) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec take_smallest(Tree1) -> {Key, Val, Tree2} when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(), - Key :: term(), - Val :: term(). +-spec take_smallest(Tree1) -> {Key, Value, Tree2} when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). take_smallest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Larger} = take_smallest1(Tree), @@ -448,10 +433,8 @@ take_smallest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Smaller1} = take_smallest1(Smaller), {Key1, Value1, {Key, Value, Smaller1, Larger}}. --spec smallest(Tree) -> {Key, Val} when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec smallest(Tree) -> {Key, Value} when + Tree :: tree(Key, Value). smallest({_, Tree}) -> smallest_1(Tree). @@ -461,11 +444,9 @@ smallest_1({Key, Value, nil, _Larger}) -> smallest_1({_Key, _Value, Smaller, _Larger}) -> smallest_1(Smaller). --spec take_largest(Tree1) -> {Key, Val, Tree2} when - Tree1 :: gb_tree(), - Tree2 :: gb_tree(), - Key :: term(), - Val :: term(). +-spec take_largest(Tree1) -> {Key, Value, Tree2} when + Tree1 :: tree(Key, Value), + Tree2 :: tree(Key, Value). take_largest({Size, Tree}) when is_integer(Size), Size >= 0 -> {Key, Value, Smaller} = take_largest1(Tree), @@ -477,10 +458,8 @@ take_largest1({Key, Value, Smaller, Larger}) -> {Key1, Value1, Larger1} = take_largest1(Larger), {Key1, Value1, {Key, Value, Smaller, Larger1}}. --spec largest(Tree) -> {Key, Val} when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec largest(Tree) -> {Key, Value} when + Tree :: tree(Key, Value). largest({_, Tree}) -> largest_1(Tree). @@ -492,10 +471,8 @@ largest_1({_Key, _Value, _Smaller, Larger}) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec to_list(Tree) -> [{Key, Val}] when - Tree :: gb_tree(), - Key :: term(), - Val :: term(). +-spec to_list(Tree) -> [{Key, Value}] when + Tree :: tree(Key, Value). to_list({_, T}) -> to_list(T, []). @@ -509,8 +486,7 @@ to_list(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec keys(Tree) -> [Key] when - Tree :: gb_tree(), - Key :: term(). + Tree :: tree(Key, Value :: term()). keys({_, T}) -> keys(T, []). @@ -521,9 +497,8 @@ keys(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec values(Tree) -> [Val] when - Tree :: gb_tree(), - Val :: term(). +-spec values(Tree) -> [Value] when + Tree :: tree(Key :: term(), Value). values({_, T}) -> values(T, []). @@ -535,8 +510,8 @@ values(nil, L) -> L. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec iterator(Tree) -> Iter when - Tree :: gb_tree(), - Iter :: iter(). + Tree :: tree(Key, Value), + Iter :: iter(Key, Value). iterator({_, T}) -> iterator_1(T). @@ -554,11 +529,9 @@ iterator({_, _, L, _} = T, As) -> iterator(nil, As) -> As. --spec next(Iter1) -> 'none' | {Key, Val, Iter2} when - Iter1 :: iter(), - Iter2 :: iter(), - Key :: term(), - Val :: term(). +-spec next(Iter1) -> 'none' | {Key, Value, Iter2} when + Iter1 :: iter(Key, Value), + Iter2 :: iter(Key, Value). next([{X, V, _, T} | As]) -> {X, V, iterator(T, As)}; @@ -568,9 +541,9 @@ next([]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec map(Function, Tree1) -> Tree2 when - Function :: fun((K :: term(), V1 :: term()) -> V2 :: term()), - Tree1 :: gb_tree(), - Tree2 :: gb_tree(). + Function :: fun((K :: Key, V1 :: Value1) -> V2 :: Value2), + Tree1 :: tree(Key, Value1), + Tree2 :: tree(Key, Value2). map(F, {Size, Tree}) when is_function(F, 2) -> {Size, map_1(F, Tree)}. diff --git a/lib/stdlib/src/queue.erl b/lib/stdlib/src/queue.erl index 4bbf5de8a5..472d503b99 100644 --- a/lib/stdlib/src/queue.erl +++ b/lib/stdlib/src/queue.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -32,6 +32,8 @@ -export([cons/2,head/1,tail/1, snoc/2,last/1,daeh/1,init/1,liat/1,lait/1]). +-export_type([queue/0, queue/1]). + %%-------------------------------------------------------------------------- %% Efficient implementation of double ended fifo queues %% @@ -44,10 +46,9 @@ %% that is; the RearList is reversed. %% -%% A declaration equivalent to the following is currently hard-coded -%% in erl_types.erl -%% -%% -opaque queue() :: {list(), list()}. +-opaque queue(Item) :: {list(Item), list(Item)}. + +-opaque queue() :: queue(_). %% Creation, inspection and conversion @@ -79,7 +80,7 @@ len(Q) -> erlang:error(badarg, [Q]). %% O(len(Q)) --spec to_list(Q :: queue()) -> list(). +-spec to_list(Q :: queue(Item)) -> list(Item). to_list({In,Out}) when is_list(In), is_list(Out) -> Out++lists:reverse(In, []); to_list(Q) -> @@ -88,7 +89,7 @@ to_list(Q) -> %% Create queue from list %% %% O(length(L)) --spec from_list(L :: list()) -> queue(). +-spec from_list(L :: list(Item)) -> queue(Item). from_list(L) when is_list(L) -> f2r(L); from_list(L) -> @@ -97,7 +98,7 @@ from_list(L) -> %% Return true or false depending on if element is in queue %% %% O(length(Q)) worst case --spec member(Item :: term(), Q :: queue()) -> boolean(). +-spec member(Item, Q :: queue(Item)) -> boolean(). member(X, {R,F}) when is_list(R), is_list(F) -> lists:member(X, R) orelse lists:member(X, F); member(X, Q) -> @@ -110,7 +111,7 @@ member(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec in(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). in(X, {[_]=In,[]}) -> {[X], In}; in(X, {In,Out}) when is_list(In), is_list(Out) -> @@ -122,7 +123,7 @@ in(X, Q) -> %% Put at least one element in each list, if it is cheap %% %% O(1) --spec in_r(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec in_r(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). in_r(X, {[],[_]=F}) -> {F,[X]}; in_r(X, {R,F}) when is_list(R), is_list(F) -> @@ -133,9 +134,9 @@ in_r(X, Q) -> %% Take from head/front %% %% O(1) amortized, O(len(Q)) worst case --spec out(Q1 :: queue()) -> - {{value, Item :: term()}, Q2 :: queue()} | - {empty, Q1 :: queue()}. +-spec out(Q1 :: queue(Item)) -> + {{value, Item}, Q2 :: queue(Item)} | + {empty, Q1 :: queue(Item)}. out({[],[]}=Q) -> {empty,Q}; out({[V],[]}) -> @@ -153,9 +154,9 @@ out(Q) -> %% Take from tail/rear %% %% O(1) amortized, O(len(Q)) worst case --spec out_r(Q1 :: queue()) -> - {{value, Item :: term()}, Q2 :: queue()} | - {empty, Q1 :: queue()}. +-spec out_r(Q1 :: queue(Item)) -> + {{value, Item}, Q2 :: queue(Item)} | + {empty, Q1 :: queue(Item)}. out_r({[],[]}=Q) -> {empty,Q}; out_r({[],[V]}) -> @@ -176,7 +177,7 @@ out_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get(Q :: queue()) -> Item :: term(). +-spec get(Q :: queue(Item)) -> Item. get({[],[]}=Q) -> erlang:error(empty, [Q]); get({R,F}) when is_list(R), is_list(F) -> @@ -195,7 +196,7 @@ get([_|R], []) -> % malformed queue -> O(len(Q)) %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec get_r(Q :: queue()) -> Item :: term(). +-spec get_r(Q :: queue(Item)) -> Item. get_r({[],[]}=Q) -> erlang:error(empty, [Q]); get_r({[H|_],F}) when is_list(F) -> @@ -210,7 +211,7 @@ get_r(Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek(Q :: queue()) -> empty | {value,Item :: term()}. +-spec peek(Q :: queue(Item)) -> empty | {value, Item}. peek({[],[]}) -> empty; peek({R,[H|_]}) when is_list(R) -> @@ -225,7 +226,7 @@ peek(Q) -> %% Return the last element in the queue %% %% O(1) since the queue is supposed to be well formed --spec peek_r(Q :: queue()) -> empty | {value,Item :: term()}. +-spec peek_r(Q :: queue(Item)) -> empty | {value, Item}. peek_r({[],[]}) -> empty; peek_r({[H|_],F}) when is_list(F) -> @@ -240,7 +241,7 @@ peek_r(Q) -> %% Remove the first element and return resulting queue %% %% O(1) amortized --spec drop(Q1 :: queue()) -> Q2 :: queue(). +-spec drop(Q1 :: queue(Item)) -> Q2 :: queue(Item). drop({[],[]}=Q) -> erlang:error(empty, [Q]); drop({[_],[]}) -> @@ -258,7 +259,7 @@ drop(Q) -> %% Remove the last element and return resulting queue %% %% O(1) amortized --spec drop_r(Q1 :: queue()) -> Q2 :: queue(). +-spec drop_r(Q1 :: queue(Item)) -> Q2 :: queue(Item). drop_r({[],[]}=Q) -> erlang:error(empty, [Q]); drop_r({[],[_]}) -> @@ -279,7 +280,7 @@ drop_r(Q) -> %% Return reversed queue %% %% O(1) --spec reverse(Q1 :: queue()) -> Q2 :: queue(). +-spec reverse(Q1 :: queue(Item)) -> Q2 :: queue(Item). reverse({R,F}) when is_list(R), is_list(F) -> {F,R}; reverse(Q) -> @@ -289,7 +290,7 @@ reverse(Q) -> %% %% Q2 empty: O(1) %% else: O(len(Q1)) --spec join(Q1 :: queue(), Q2 :: queue()) -> Q3 :: queue(). +-spec join(Q1 :: queue(Item), Q2 :: queue(Item)) -> Q3 :: queue(Item). join({R,F}=Q, {[],[]}) when is_list(R), is_list(F) -> Q; join({[],[]}, {R,F}=Q) when is_list(R), is_list(F) -> @@ -303,8 +304,8 @@ join(Q1, Q2) -> %% %% N = 0..len(Q) %% O(max(N, len(Q))) --spec split(N :: non_neg_integer(), Q1 :: queue()) -> - {Q2 :: queue(),Q3 :: queue()}. +-spec split(N :: non_neg_integer(), Q1 :: queue(Item)) -> + {Q2 :: queue(Item),Q3 :: queue(Item)}. split(0, {R,F}=Q) when is_list(R), is_list(F) -> {{[],[]},Q}; split(N, {R,F}=Q) when is_integer(N), N >= 1, is_list(R), is_list(F) -> @@ -345,8 +346,8 @@ split_r1_to_f2(N, [X|R1], F1, R2, F2) -> %% %% Fun(_) -> List: O(length(List) * len(Q)) %% else: O(len(Q) --spec filter(Fun, Q1 :: queue()) -> Q2 :: queue() when - Fun :: fun((Item :: term()) -> boolean() | list()). +-spec filter(Fun, Q1 :: queue(Item)) -> Q2 :: queue(Item) when + Fun :: fun((Item) -> boolean() | list(Item)). filter(Fun, {R0,F0}) when is_function(Fun, 1), is_list(R0), is_list(F0) -> F = filter_f(Fun, F0), R = filter_r(Fun, R0), @@ -422,7 +423,7 @@ filter_r(Fun, [X|R0]) -> %% Cons to head %% --spec cons(Item :: term(), Q1 :: queue()) -> Q2 :: queue(). +-spec cons(Item, Q1 :: queue(Item)) -> Q2 :: queue(Item). cons(X, Q) -> in_r(X, Q). @@ -431,7 +432,7 @@ cons(X, Q) -> %% Return the first element in the queue %% %% O(1) since the queue is supposed to be well formed --spec head(Q :: queue()) -> Item :: term(). +-spec head(Q :: queue(Item)) -> Item. head({[],[]}=Q) -> erlang:error(empty, [Q]); head({R,F}) when is_list(R), is_list(F) -> @@ -441,7 +442,7 @@ head(Q) -> %% Remove head element and return resulting queue %% --spec tail(Q1 :: queue()) -> Q2 :: queue(). +-spec tail(Q1 :: queue(Item)) -> Q2 :: queue(Item). tail(Q) -> drop(Q). @@ -449,22 +450,22 @@ tail(Q) -> %% Cons to tail %% --spec snoc(Q1 :: queue(), Item :: term()) -> Q2 :: queue(). +-spec snoc(Q1 :: queue(Item), Item) -> Q2 :: queue(Item). snoc(Q, X) -> in(X, Q). %% Return last element --spec daeh(Q :: queue()) -> Item :: term(). +-spec daeh(Q :: queue(Item)) -> Item. daeh(Q) -> get_r(Q). --spec last(Q :: queue()) -> Item :: term(). +-spec last(Q :: queue(Item)) -> Item. last(Q) -> get_r(Q). %% Remove last element and return resulting queue --spec liat(Q1 :: queue()) -> Q2 :: queue(). +-spec liat(Q1 :: queue(Item)) -> Q2 :: queue(Item). liat(Q) -> drop_r(Q). --spec lait(Q1 :: queue()) -> Q2 :: queue(). +-spec lait(Q1 :: queue(Item)) -> Q2 :: queue(Item). lait(Q) -> drop_r(Q). %% Oops, mis-spelled 'tail' reversed. Forget this one. --spec init(Q1 :: queue()) -> Q2 :: queue(). +-spec init(Q1 :: queue(Item)) -> Q2 :: queue(Item). init(Q) -> drop_r(Q). %%-------------------------------------------------------------------------- diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl index ebf011a7d9..be4b600f25 100644 --- a/lib/stdlib/src/sets.erl +++ b/lib/stdlib/src/sets.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -43,6 +43,8 @@ -export([subtract/2,is_subset/2]). -export([fold/3,filter/2]). +-export_type([set/0, set/1]). + %% Note: mk_seg/1 must be changed too if seg_size is changed. -define(seg_size, 16). -define(max_seg, 32). @@ -54,7 +56,8 @@ %%------------------------------------------------------------------------------ -type seg() :: tuple(). --type segs() :: tuple(). +-type segs(E) :: tuple() + | E. % dummy %% Define a hash set. The default values are the standard ones. -record(set, @@ -65,14 +68,12 @@ exp_size=?exp_size :: non_neg_integer(), % Size to expand at con_size=?con_size :: non_neg_integer(), % Size to contract at empty :: seg(), % Empty segment - segs :: segs() % Segments + segs :: segs(_) % Segments }). -%% A declaration equivalent to the following one is hard-coded in erl_types. -%% That declaration contains hard-coded information about the #set{} -%% record and the types of its fields. So, please make sure that any -%% changes to its structure are also propagated to erl_types.erl. -%% -%% -opaque set() :: #set{}. + +-opaque set() :: set(_). + +-opaque set(Element) :: #set{segs :: segs(Element)}. %%------------------------------------------------------------------------------ @@ -98,24 +99,23 @@ size(S) -> S#set.size. %% to_list(Set) -> [Elem]. %% Return the elements in Set as a list. -spec to_list(Set) -> List when - Set :: set(), - List :: [term()]. + Set :: set(Element), + List :: [Element]. to_list(S) -> fold(fun (Elem, List) -> [Elem|List] end, [], S). %% from_list([Elem]) -> Set. %% Build a set from the elements in List. -spec from_list(List) -> Set when - List :: [term()], - Set :: set(). + List :: [Element], + Set :: set(Element). from_list(L) -> lists:foldl(fun (E, S) -> add_element(E, S) end, new(), L). %% is_element(Element, Set) -> boolean(). %% Return 'true' if Element is an element of Set, else 'false'. -spec is_element(Element, Set) -> boolean() when - Element :: term(), - Set :: set(). + Set :: set(Element). is_element(E, S) -> Slot = get_slot(S, E), Bkt = get_bucket(S, Slot), @@ -124,9 +124,8 @@ is_element(E, S) -> %% add_element(Element, Set) -> Set. %% Return Set with Element inserted in it. -spec add_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). add_element(E, S0) -> Slot = get_slot(S0, E), {S1,Ic} = on_bucket(fun (B0) -> add_bkt_el(E, B0, B0) end, S0, Slot), @@ -141,9 +140,8 @@ add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}. %% del_element(Element, Set) -> Set. %% Return Set but with Element removed. -spec del_element(Element, Set1) -> Set2 when - Element :: term(), - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). del_element(E, S0) -> Slot = get_slot(S0, E), {S1,Dc} = on_bucket(fun (B0) -> del_bkt_el(E, B0) end, S0, Slot), @@ -159,9 +157,9 @@ del_bkt_el(_, []) -> {[],0}. %% union(Set1, Set2) -> Set %% Return the union of Set1 and Set2. -spec union(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). union(S1, S2) when S1#set.size < S2#set.size -> fold(fun (E, S) -> add_element(E, S) end, S2, S1); union(S1, S2) -> @@ -170,14 +168,14 @@ union(S1, S2) -> %% union([Set]) -> Set %% Return the union of the list of sets. -spec union(SetList) -> Set when - SetList :: [set()], - Set :: set(). + SetList :: [set(Element)], + Set :: set(Element). union([S1,S2|Ss]) -> union1(union(S1, S2), Ss); union([S]) -> S; union([]) -> new(). --spec union1(set(), [set()]) -> set(). +-spec union1(set(E), [set(E)]) -> set(E). union1(S1, [S2|Ss]) -> union1(union(S1, S2), Ss); union1(S1, []) -> S1. @@ -185,9 +183,9 @@ union1(S1, []) -> S1. %% intersection(Set1, Set2) -> Set. %% Return the intersection of Set1 and Set2. -spec intersection(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). intersection(S1, S2) when S1#set.size < S2#set.size -> filter(fun (E) -> is_element(E, S2) end, S1); intersection(S1, S2) -> @@ -196,13 +194,13 @@ intersection(S1, S2) -> %% intersection([Set]) -> Set. %% Return the intersection of the list of sets. -spec intersection(SetList) -> Set when - SetList :: [set(),...], - Set :: set(). + SetList :: [set(Element),...], + Set :: set(Element). intersection([S1,S2|Ss]) -> intersection1(intersection(S1, S2), Ss); intersection([S]) -> S. --spec intersection1(set(), [set()]) -> set(). +-spec intersection1(set(E), [set(E)]) -> set(E). intersection1(S1, [S2|Ss]) -> intersection1(intersection(S1, S2), Ss); intersection1(S1, []) -> S1. @@ -210,8 +208,8 @@ intersection1(S1, []) -> S1. %% is_disjoint(Set1, Set2) -> boolean(). %% Check whether Set1 and Set2 are disjoint. -spec is_disjoint(Set1, Set2) -> boolean() when - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). is_disjoint(S1, S2) when S1#set.size < S2#set.size -> fold(fun (_, false) -> false; (E, true) -> not is_element(E, S2) @@ -225,9 +223,9 @@ is_disjoint(S1, S2) -> %% Return all and only the elements of Set1 which are not also in %% Set2. -spec subtract(Set1, Set2) -> Set3 when - Set1 :: set(), - Set2 :: set(), - Set3 :: set(). + Set1 :: set(Element), + Set2 :: set(Element), + Set3 :: set(Element). subtract(S1, S2) -> filter(fun (E) -> not is_element(E, S2) end, S1). @@ -235,34 +233,34 @@ subtract(S1, S2) -> %% Return 'true' when every element of Set1 is also a member of %% Set2, else 'false'. -spec is_subset(Set1, Set2) -> boolean() when - Set1 :: set(), - Set2 :: set(). + Set1 :: set(Element), + Set2 :: set(Element). is_subset(S1, S2) -> fold(fun (E, Sub) -> Sub andalso is_element(E, S2) end, true, S1). %% fold(Fun, Accumulator, Set) -> Accumulator. %% Fold function Fun over all elements in Set and return Accumulator. -spec fold(Function, Acc0, Set) -> Acc1 when - Function :: fun((E :: term(),AccIn) -> AccOut), - Set :: set(), - Acc0 :: T, - Acc1 :: T, - AccIn :: T, - AccOut :: T. + Function :: fun((Element, AccIn) -> AccOut), + Set :: set(Element), + Acc0 :: Acc, + Acc1 :: Acc, + AccIn :: Acc, + AccOut :: Acc. fold(F, Acc, D) -> fold_set(F, Acc, D). %% filter(Fun, Set) -> Set. %% Filter Set with Fun. -spec filter(Pred, Set1) -> Set2 when - Pred :: fun((E :: term()) -> boolean()), - Set1 :: set(), - Set2 :: set(). + Pred :: fun((Element) -> boolean()), + Set1 :: set(Element), + Set2 :: set(Element). filter(F, D) -> filter_set(F, D). %% get_slot(Hashdb, Key) -> Slot. %% Get the slot. First hash on the new range, if we hit a bucket %% which has not been split use the unsplit buddy bucket. --spec get_slot(set(), term()) -> non_neg_integer(). +-spec get_slot(set(E), E) -> non_neg_integer(). get_slot(T, Key) -> H = erlang:phash(Key, T#set.maxn), if @@ -276,8 +274,8 @@ get_bucket(T, Slot) -> get_bucket_s(T#set.segs, Slot). %% on_bucket(Fun, Hashdb, Slot) -> {NewHashDb,Result}. %% Apply Fun to the bucket in Slot and replace the returned bucket. --spec on_bucket(fun((_) -> {[_], 0 | 1}), set(), non_neg_integer()) -> - {set(), 0 | 1}. +-spec on_bucket(fun((_) -> {[_], 0 | 1}), set(E), non_neg_integer()) -> + {set(E), 0 | 1}. on_bucket(F, T, Slot) -> SegI = ((Slot-1) div ?seg_size) + 1, BktI = ((Slot-1) rem ?seg_size) + 1, @@ -351,7 +349,7 @@ put_bucket_s(Segs, Slot, Bkt) -> Seg = setelement(BktI, element(SegI, Segs), Bkt), setelement(SegI, Segs, Seg). --spec maybe_expand(set(), 0 | 1) -> set(). +-spec maybe_expand(set(E), 0 | 1) -> set(E). maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size -> T = maybe_expand_segs(T0), %Do we need more segments. N = T#set.n + 1, %Next slot to expand into @@ -369,14 +367,14 @@ maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size -> segs = Segs2}; maybe_expand(T, Ic) -> T#set{size = T#set.size + Ic}. --spec maybe_expand_segs(set()) -> set(). +-spec maybe_expand_segs(set(E)) -> set(E). maybe_expand_segs(T) when T#set.n =:= T#set.maxn -> T#set{maxn = 2 * T#set.maxn, bso = 2 * T#set.bso, segs = expand_segs(T#set.segs, T#set.empty)}; maybe_expand_segs(T) -> T. --spec maybe_contract(set(), non_neg_integer()) -> set(). +-spec maybe_contract(set(E), non_neg_integer()) -> set(E). maybe_contract(T, Dc) when T#set.size - Dc < T#set.con_size, T#set.n > ?seg_size -> N = T#set.n, @@ -395,7 +393,7 @@ maybe_contract(T, Dc) when T#set.size - Dc < T#set.con_size, segs = Segs2}); maybe_contract(T, Dc) -> T#set{size = T#set.size - Dc}. --spec maybe_contract_segs(set()) -> set(). +-spec maybe_contract_segs(set(E)) -> set(E). maybe_contract_segs(T) when T#set.n =:= T#set.bso -> T#set{maxn = T#set.maxn div 2, bso = T#set.bso div 2, @@ -422,7 +420,7 @@ mk_seg(16) -> {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}. %% of segments. We special case the powers of 2 upto 32, this should %% catch most case. N.B. the last element in the segments tuple is %% an extra element containing a default empty segment. --spec expand_segs(segs(), seg()) -> segs(). +-spec expand_segs(segs(E), seg()) -> segs(E). expand_segs({B1}, Empty) -> {B1,Empty}; expand_segs({B1,B2}, Empty) -> @@ -440,7 +438,7 @@ expand_segs(Segs, Empty) -> list_to_tuple(tuple_to_list(Segs) ++ lists:duplicate(tuple_size(Segs), Empty)). --spec contract_segs(segs()) -> segs(). +-spec contract_segs(segs(E)) -> segs(E). contract_segs({B1,_}) -> {B1}; contract_segs({B1,B2,_,_}) -> diff --git a/lib/stdlib/src/sofs.erl b/lib/stdlib/src/sofs.erl index 34eb224647..0bd67db100 100644 --- a/lib/stdlib/src/sofs.erl +++ b/lib/stdlib/src/sofs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1509,7 +1509,7 @@ family_projection(SetFun, F) when ?IS_SET(F) -> %%% -spec(family_to_digraph(Family) -> Graph when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family()). family_to_digraph(F) when ?IS_SET(F) -> case ?TYPE(F) of @@ -1519,7 +1519,7 @@ family_to_digraph(F) when ?IS_SET(F) -> end. -spec(family_to_digraph(Family, GraphType) -> Graph when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family(), GraphType :: [digraph:d_type()]). family_to_digraph(F, Type) when ?IS_SET(F) -> @@ -1541,7 +1541,7 @@ family_to_digraph(F, Type) when ?IS_SET(F) -> end. -spec(digraph_to_family(Graph) -> Family when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family()). digraph_to_family(G) -> case catch digraph_family(G) of @@ -1550,7 +1550,7 @@ digraph_to_family(G) -> end. -spec(digraph_to_family(Graph, Type) -> Family when - Graph :: digraph(), + Graph :: digraph:graph(), Family :: family(), Type :: type()). digraph_to_family(G, T) -> diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 974583bc28..ede2742875 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -77,14 +77,15 @@ modules = [] :: modules()}). -type child_rec() :: #child{}. --define(DICT, dict). +-define(DICTS, dict). +-define(DICT, dict:dict). -define(SETS, sets). --define(SET, set). +-define(SET, sets:set). -record(state, {name, strategy :: strategy(), children = [] :: [child_rec()], - dynamics :: ?DICT() | ?SET(), + dynamics :: ?DICT(pid(), list()) | ?SET(pid()), intensity :: non_neg_integer(), period :: pos_integer(), restarts = [], @@ -444,7 +445,7 @@ handle_call(which_children, _From, #state{children = [#child{restart_type = RTyp State) when ?is_simple(State) -> Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods}; ({Pid, _}) -> {undefined, Pid, CT, Mods} end, - ?DICT:to_list(dynamics_db(RType, State#state.dynamics))), + ?DICTS:to_list(dynamics_db(RType, State#state.dynamics))), {reply, Reply, State}; handle_call(which_children, _From, State) -> @@ -483,7 +484,7 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = RTy child_type = CT}]} = State) when ?is_simple(State) -> {Active, Count} = - ?DICT:fold(fun(Pid, _Val, {Alive, Tot}) -> + ?DICTS:fold(fun(Pid, _Val, {Alive, Tot}) -> case is_pid(Pid) andalso is_process_alive(Pid) of true -> {Alive+1, Tot +1}; @@ -777,17 +778,17 @@ restart(Child, State) -> restart(simple_one_for_one, Child, State) -> #child{pid = OldPid, mfargs = {M, F, A}} = Child, - Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type, + Dynamics = ?DICTS:erase(OldPid, dynamics_db(Child#child.restart_type, State#state.dynamics)), case do_start_child_i(M, F, A) of {ok, Pid} -> - NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, {ok, NState}; {ok, Pid, _Extra} -> - NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, + NState = State#state{dynamics = ?DICTS:store(Pid, A, Dynamics)}, {ok, NState}; {error, Error} -> - NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A, + NState = State#state{dynamics = ?DICTS:store(restarting(OldPid), A, Dynamics)}, report_error(start_error, Error, Child, State#state.name), {try_again, NState} @@ -980,7 +981,7 @@ terminate_dynamic_children(Child, Dynamics, SupName) -> wait_dynamic_children(Child, Pids, Sz, TRef, EStack0) end, %% Unroll stacked errors and report them - ?DICT:fold(fun(Reason, Ls, _) -> + ?DICTS:fold(fun(Reason, Ls, _) -> report_error(shutdown_error, Reason, Child#child{pid=Ls}, SupName) end, ok, EStack). @@ -994,22 +995,22 @@ monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) -> {error, normal} -> {Pids, EStack}; {error, Reason} -> - {Pids, ?DICT:append(Reason, P, EStack)} + {Pids, ?DICTS:append(Reason, P, EStack)} end - end, {?SETS:new(), ?DICT:new()}, Dynamics); + end, {?SETS:new(), ?DICTS:new()}, Dynamics); monitor_dynamic_children(#child{restart_type=RType}, Dynamics) -> - ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) -> + ?DICTS:fold(fun(P, _, {Pids, EStack}) when is_pid(P) -> case monitor_child(P) of ok -> {?SETS:add_element(P, Pids), EStack}; {error, normal} when RType =/= permanent -> {Pids, EStack}; {error, Reason} -> - {Pids, ?DICT:append(Reason, P, EStack)} + {Pids, ?DICTS:append(Reason, P, EStack)} end; (?restarting(_), _, {Pids, EStack}) -> {Pids, EStack} - end, {?SETS:new(), ?DICT:new()}, Dynamics). + end, {?SETS:new(), ?DICTS:new()}, Dynamics). wait_dynamic_children(_Child, _Pids, 0, undefined, EStack) -> @@ -1033,7 +1034,7 @@ wait_dynamic_children(#child{shutdown=brutal_kill} = Child, Pids, Sz, {'DOWN', _MRef, process, Pid, Reason} -> wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, - TRef, ?DICT:append(Reason, Pid, EStack)) + TRef, ?DICTS:append(Reason, Pid, EStack)) end; wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, TRef, EStack) -> @@ -1048,7 +1049,7 @@ wait_dynamic_children(#child{restart_type=RType} = Child, Pids, Sz, {'DOWN', _MRef, process, Pid, Reason} -> wait_dynamic_children(Child, ?SETS:del_element(Pid, Pids), Sz-1, - TRef, ?DICT:append(Reason, Pid, EStack)); + TRef, ?DICTS:append(Reason, Pid, EStack)); {timeout, TRef, kill} -> ?SETS:fold(fun(P, _) -> exit(P, kill) end, ok, Pids), @@ -1073,12 +1074,12 @@ save_child(Child, #state{children = Children} = State) -> save_dynamic_child(temporary, Pid, _, #state{dynamics = Dynamics} = State) -> State#state{dynamics = ?SETS:add_element(Pid, dynamics_db(temporary, Dynamics))}; save_dynamic_child(RestartType, Pid, Args, #state{dynamics = Dynamics} = State) -> - State#state{dynamics = ?DICT:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. + State#state{dynamics = ?DICTS:store(Pid, Args, dynamics_db(RestartType, Dynamics))}. dynamics_db(temporary, undefined) -> ?SETS:new(); dynamics_db(_, undefined) -> - ?DICT:new(); + ?DICTS:new(); dynamics_db(_,Dynamics) -> Dynamics. @@ -1087,14 +1088,14 @@ dynamic_child_args(Pid, Dynamics) -> true -> {ok, undefined}; false -> - ?DICT:find(Pid, Dynamics) + ?DICTS:find(Pid, Dynamics) end. state_del_child(#child{pid = Pid, restart_type = temporary}, State) when ?is_simple(State) -> NDynamics = ?SETS:del_element(Pid, dynamics_db(temporary, State#state.dynamics)), State#state{dynamics = NDynamics}; state_del_child(#child{pid = Pid, restart_type = RType}, State) when ?is_simple(State) -> - NDynamics = ?DICT:erase(Pid, dynamics_db(RType, State#state.dynamics)), + NDynamics = ?DICTS:erase(Pid, dynamics_db(RType, State#state.dynamics)), State#state{dynamics = NDynamics}; state_del_child(Child, State) -> NChildren = del_child(Child#child.name, State#state.children), @@ -1157,7 +1158,7 @@ is_dynamic_pid(Pid, Dynamics) -> true -> ?SETS:is_element(Pid, Dynamics); false -> - ?DICT:is_key(Pid, Dynamics) + ?DICTS:is_key(Pid, Dynamics) end. replace_child(Child, State) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 48f50d5f43..1614a2722f 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -60,7 +60,8 @@ format_warn/1, on_load_successful/1, on_load_failing/1, too_many_arguments/1, - basic_errors/1,bin_syntax_errors/1 + basic_errors/1,bin_syntax_errors/1, + predef/1 ]). % Default timetrap timeout (set in init_per_testcase). @@ -87,7 +88,7 @@ all() -> otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, otp_11254,export_all, bif_clash, behaviour_basic, behaviour_multiple, otp_7550, otp_8051, format_warn, {group, on_load}, - too_many_arguments, basic_errors, bin_syntax_errors]. + too_many_arguments, basic_errors, bin_syntax_errors, predef]. groups() -> [{unused_vars_warn, [], @@ -3241,6 +3242,23 @@ bin_syntax_errors(Config) -> [] = run(Config, Ts), ok. +predef(doc) -> + "Predefined types: array(), digraph(), and so on"; +predef(suite) -> []; +predef(Config) when is_list(Config) -> + W = get_compilation_warnings(Config, "predef", []), + [] = W, + W2 = get_compilation_warnings(Config, "predef2", []), + [{7,erl_lint,{deprecated_type,{array,0},{array,array},"OTP 18.0"}}, + {12,erl_lint,{deprecated_type,{dict,0},{dict,dict},"OTP 18.0"}}, + {17,erl_lint,{deprecated_type,{digraph,0},{digraph,graph},"OTP 18.0"}}, + {27,erl_lint,{deprecated_type,{gb_set,0},{gb_sets,set},"OTP 18.0"}}, + {32,erl_lint,{deprecated_type,{gb_tree,0},{gb_trees,tree},"OTP 18.0"}}, + {37,erl_lint,{deprecated_type,{queue,0},{queue,queue},"OTP 18.0"}}, + {42,erl_lint,{deprecated_type,{set,0},{sets,set},"OTP 18.0"}}, + {47,erl_lint,{deprecated_type,{tid,0},{ets,tid},"OTP 18.0"}}] = W2, + ok. + run(Config, Tests) -> F = fun({N,P,Ws,E}, BadL) -> case catch run_test(Config, P, Ws) of @@ -3263,8 +3281,10 @@ get_compilation_warnings(Conf, Filename, Warnings) -> FileS = binary_to_list(Bin), {match,[{Start,Length}|_]} = re:run(FileS, "-module.*\\n"), Test = lists:nthtail(Start+Length, FileS), - {warnings, Ws} = run_test(Conf, Test, Warnings), - Ws. + case run_test(Conf, Test, Warnings) of + {warnings, Ws} -> Ws; + [] -> [] + end. %% Compiles a test module and returns the list of errors and warnings. diff --git a/lib/stdlib/test/erl_lint_SUITE_data/predef.erl b/lib/stdlib/test/erl_lint_SUITE_data/predef.erl new file mode 100644 index 0000000000..c2364fd1c2 --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/predef.erl @@ -0,0 +1,67 @@ +-module(predef). + +-export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1, + queue/1, set/1, tid/0, tid2/0]). + +-export_type([array/0, digraph/0, gb_set/0]). + +%% Before R17B local re-definitions of pre-defined opaque types were +%% ignored but did not generate any warning. +-opaque array() :: atom(). +-opaque digraph() :: atom(). +-opaque gb_set() :: atom(). +-type dict() :: atom(). +-type gb_tree() :: atom(). +-type queue() :: atom(). +-type set() :: atom(). +-type tid() :: atom(). + +-spec array(array()) -> array:array(). + +array(A) -> + array:relax(A). + +-spec dict(dict()) -> dict:dict(). + +dict(D) -> + dict:store(1, a, D). + +-spec digraph(digraph()) -> [digraph:edge()]. + +digraph(G) -> + digraph:edges(G). + +-spec digraph2(digraph:graph()) -> [digraph:edge()]. + +digraph2(G) -> + digraph:edges(G). + +-spec gb_set(gb_set()) -> gb_sets:set(). + +gb_set(S) -> + gb_sets:balance(S). + +-spec gb_tree(gb_tree()) -> gb_trees:tree(). + +gb_tree(S) -> + gb_trees:balance(S). + +-spec queue(queue()) -> queue:queue(). + +queue(Q) -> + queue:reverse(Q). + +-spec set(set()) -> sets:set(). + +set(S) -> + sets:union([S]). + +-spec tid() -> tid(). + +tid() -> + ets:new(tid, []). + +-spec tid2() -> ets:tid(). + +tid2() -> + ets:new(tid, []). diff --git a/lib/stdlib/test/erl_lint_SUITE_data/predef2.erl b/lib/stdlib/test/erl_lint_SUITE_data/predef2.erl new file mode 100644 index 0000000000..b1d941a49a --- /dev/null +++ b/lib/stdlib/test/erl_lint_SUITE_data/predef2.erl @@ -0,0 +1,56 @@ +-module(predef2). + +-export([array/1, dict/1, digraph/1, digraph2/1, gb_set/1, gb_tree/1, + queue/1, set/1, tid/0, tid2/0]). + +-export_type([array/0, digraph/0, gb_set/0]). + +-spec array(array()) -> array:array(). + +array(A) -> + array:relax(A). + +-spec dict(dict()) -> dict:dict(). + +dict(D) -> + dict:store(1, a, D). + +-spec digraph(digraph()) -> [digraph:edge()]. + +digraph(G) -> + digraph:edges(G). + +-spec digraph2(digraph:graph()) -> [digraph:edge()]. + +digraph2(G) -> + digraph:edges(G). + +-spec gb_set(gb_set()) -> gb_sets:set(). + +gb_set(S) -> + gb_sets:balance(S). + +-spec gb_tree(gb_tree()) -> gb_trees:tree(). + +gb_tree(S) -> + gb_trees:balance(S). + +-spec queue(queue()) -> queue:queue(). + +queue(Q) -> + queue:reverse(Q). + +-spec set(set()) -> sets:set(). + +set(S) -> + sets:union([S]). + +-spec tid() -> tid(). + +tid() -> + ets:new(tid, []). + +-spec tid2() -> ets:tid(). + +tid2() -> + ets:new(tid, []). diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index e4665b99fc..2f0488abec 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -288,7 +288,7 @@ mapfoldl(_, S, []) -> %% %% @see //stdlib/sets --spec variables(erl_syntax:syntaxTree()) -> set(). +-spec variables(erl_syntax:syntaxTree()) -> sets:set(atom()). variables(Tree) -> variables(Tree, sets:new()). @@ -343,7 +343,7 @@ default_variable_name(N) -> %% %% @see new_variable_name/2 --spec new_variable_name(set()) -> atom(). +-spec new_variable_name(sets:set(atom())) -> atom(). new_variable_name(S) -> new_variable_name(fun default_variable_name/1, S). @@ -369,7 +369,7 @@ new_variable_name(S) -> %% @see //stdlib/sets %% @see //stdlib/random --spec new_variable_name(fun((integer()) -> atom()), set()) -> atom(). +-spec new_variable_name(fun((integer()) -> atom()), sets:set(atom())) -> atom(). new_variable_name(F, S) -> R = start_range(S), @@ -416,7 +416,7 @@ generate(_Key, Range) -> %% %% @see new_variable_name/1 --spec new_variable_names(integer(), set()) -> [atom()]. +-spec new_variable_names(integer(), sets:set(atom())) -> [atom()]. new_variable_names(N, S) -> new_variable_names(N, fun default_variable_name/1, S). @@ -432,7 +432,7 @@ new_variable_names(N, S) -> %% %% @see new_variable_name/2 --spec new_variable_names(integer(), fun((integer()) -> atom()), set()) -> +-spec new_variable_names(integer(), fun((integer()) -> atom()), sets:set(atom())) -> [atom()]. new_variable_names(N, F, S) when is_integer(N) -> diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl index 7444d8dc67..38e0c2099b 100644 --- a/lib/syntax_tools/src/erl_tidy.erl +++ b/lib/syntax_tools/src/erl_tidy.erl @@ -14,7 +14,7 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% @copyright 1999-2006 Richard Carlsson +%% @copyright 1999-2014 Richard Carlsson %% @author Richard Carlsson %% @end %% ===================================================================== @@ -958,7 +958,7 @@ hidden_uses_2(Tree, Used) -> -record(env, {file :: file:filename(), module :: atom(), current :: fa(), - imports = dict:new() :: dict(), + imports = dict:new() :: dict:dict(atom(), atom()), context = normal :: context(), verbosity = 1 :: 0 | 1 | 2, quiet = false :: boolean(), @@ -970,12 +970,12 @@ hidden_uses_2(Tree, Used) -> old_guard_tests = false :: boolean()}). -record(st, {varc :: non_neg_integer(), - used = sets:new() :: set(), - imported :: set(), - vars :: set(), - functions :: set(), + used = sets:new() :: sets:set({atom(), arity()}), + imported :: sets:set({atom(), arity()}), + vars :: sets:set(atom()), + functions :: sets:set({atom(), arity()}), new_forms = [] :: [erl_syntax:syntaxTree()], - rename :: dict()}). + rename :: dict:dict(mfa(), {atom(), atom()})}). visit_used(Names, Defs, Roots, Imports, Module, Opts) -> File = proplists:get_value(file, Opts, ""), diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl index 19b1cd592f..e6aff7b20a 100644 --- a/lib/syntax_tools/src/igor.erl +++ b/lib/syntax_tools/src/igor.erl @@ -14,7 +14,7 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% @copyright 1998-2006 Richard Carlsson +%% @copyright 1998-2014 Richard Carlsson %% @author Richard Carlsson %% @end %% ===================================================================== @@ -695,7 +695,7 @@ merge_files1(Files, Opts) -> preserved :: boolean(), no_headers :: boolean(), notes :: notes(), - redirect :: dict(), % = dict(atom(), atom()) + redirect :: dict:dict(atom(), atom()), no_imports :: ordsets:ordset(atom()), options :: [option()] }). @@ -727,7 +727,7 @@ merge_sources(Name, Sources, Opts) -> %% Data structure for keeping state during transformation. --record(state, {export :: set()}). +-record(state, {export :: sets:set(atom(), arity())}). state__add_export(Name, Arity, S) -> S#state{export = sets:add_element({Name, Arity}, @@ -1039,7 +1039,7 @@ make_stub(M, Map, Env) -> -type atts() :: 'delete' | 'kill'. -type file_atts() :: 'delete' | 'keep' | 'kill'. --record(filter, {records :: set(), +-record(filter, {records :: sets:set(atom()), file_attributes :: file_atts(), attributes :: atts()}). @@ -1588,17 +1588,17 @@ alias_expansions_2(Modules, Table) -> -record(code, {module :: atom(), target :: atom(), - sources :: set(), % set(atom()), - static :: set(), % set(atom()), - safe :: set(), % set(atom()), + sources :: sets:set(atom()), + static :: sets:set(atom()), + safe :: sets:set(atom()), preserved :: boolean(), no_headers :: boolean(), notes :: notes(), map :: map_fun(), renaming :: fun((atom()) -> map_fun()), - expand :: dict(), % = dict({atom(), integer()}, - % {atom(), {atom(), integer()}}) - redirect :: dict() % = dict(atom(), atom()) + expand :: dict:dict({atom(), integer()}, + {atom(), {atom(), integer()}}), + redirect :: dict:dict(atom(), atom()) }). %% `Trees' must be a list of syntax trees of type `form_list'. The diff --git a/lib/tools/src/xref_compiler.erl b/lib/tools/src/xref_compiler.erl index f0fed502a5..c4b5c04c12 100644 --- a/lib/tools/src/xref_compiler.erl +++ b/lib/tools/src/xref_compiler.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -885,7 +885,7 @@ evaluate([pop | P], T, [_ | S]) -> evaluate([], T, [R]) -> {T, R}. -%% (PossibleGraph, 1 | -1, dict()) -> dict() +%% (PossibleGraph, 1 | -1, dict:dict()) -> dict:dict() %% Use the same table for everything... Here: Reference counters for digraphs. update_graph_counter(Value, Inc, T) -> case catch digraph:info(Value) of diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 7b72165e6f..49c397a140 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -437,7 +437,7 @@ regexpr({ModExpr, FunExpr, ArityExpr}, Var) -> V2 end. -%% -> digraph() +%% -> digraph:graph() relation_to_graph(S) -> G = digraph:new(), Fun = fun({From, To}) -> diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index 20ae4d6066..572bf24ca4 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2012. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1094,7 +1094,7 @@ rcv_ext_types(Self, ExtTypes) -> %% specialized for the uses in this module %%-------------------------------------------------------------------- --type map_dict() :: dict(). +-type map_dict() :: dict:dict(). -spec map__new() -> map_dict(). map__new() -> -- cgit v1.2.3