From 9d870a01dd2fc331b987905b981c52f57a44669f Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Wed, 1 Feb 2012 16:34:08 +0100 Subject: Reintroduce sensitive BIFs in erl_bif_types This involves exception BIF's, guar BIF's and some other complicated BIF's Also some minor corrections to documentation and specs in erlang.erl Added comment for each spec in erlang.erl shadowed by erl_bif_types. Dialyzer test should now run well except for one or two cases. --- erts/doc/src/erlang.xml | 35 +++++++--- erts/preloaded/ebin/erlang.beam | Bin 84720 -> 84876 bytes erts/preloaded/src/erlang.erl | 56 +++++++++++++-- lib/hipe/cerl/erl_bif_types.erl | 150 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 215 insertions(+), 26 deletions(-) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 7838cffded..e5ea517492 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -3191,7 +3191,8 @@ os_prompt% Set process flag priority for the calling process -

This sets the process priority. Level is an atom. +

+ This sets the process priority. Level is an atom. There are currently four priority levels: low, normal, high, and max. The default priority level is normal. NOTE: The @@ -3333,6 +3334,8 @@ os_prompt% + + Information about a process

Returns a list containing InfoTuples with @@ -3889,7 +3892,7 @@ true

Starts a timer which will send the message Msg to Dest after Time milliseconds.

If Dest is a pid() it has to be a pid() of a local process, dead or alive.

-

The Time value can, in the current implementation, not be grater than 4294967295.

+

The Time value can, in the current implementation, not be greater than 4294967295.

If Dest is an atom(), it is supposed to be the name of a registered process. The process referred to by the name is looked up at the time of delivery. No error is given if @@ -4314,7 +4317,7 @@ true {timeout, TimerRef, Msg} to Dest after Time milliseconds.

If Dest is a pid() it has to be a pid() of a local process, dead or alive.

-

The Time value can, in the current implementation, not be grater than 4294967295.

+

The Time value can, in the current implementation, not be greater than 4294967295.

If Dest is an atom(), it is supposed to be the name of a registered process. The process referred to by the name is looked up at the time of delivery. No error is given if @@ -4345,7 +4348,8 @@ true Information about exact reductions -

NOTE: statistics(exact_reductions) is +

+ NOTE: statistics(exact_reductions) is a more expensive operation than statistics(reductions) especially on an Erlang machine with SMP support.

@@ -4371,7 +4375,8 @@ true Information about reductions -

NOTE: From erts version 5.5 (OTP release R11B) +

+ NOTE: From erts version 5.5 (OTP release R11B) this value does not include reductions performed in current time slices of currently scheduled processes. If an exact value is wanted, use @@ -4525,12 +4530,14 @@ true - + + Set system flag cpu_topology -

This argument is deprecated and +

+ This argument is deprecated and scheduled for removal in erts-5.10/OTP-R16. Instead of using this argument you are advised to use the erl command line argument +sct. @@ -4616,7 +4623,8 @@ true Set system flag multi_scheduling -

If multi-scheduling is enabled, more than one scheduler +

+ If multi-scheduling is enabled, more than one scheduler thread is used by the emulator. Multi-scheduling can be blocked. When multi-scheduling has been blocked, only one scheduler thread will schedule Erlang processes.

@@ -4655,7 +4663,8 @@ true Set system flag scheduler_bind_type -

This argument is deprecated and +

+ This argument is deprecated and scheduled for removal in erts-5.10/OTP-R16. Instead of using this argument you are advised to use the erl command line argument +sbt. @@ -4772,7 +4781,8 @@ true Set system flag schedulers_online -

Sets the amount of schedulers online. Valid range is +

+ Sets the amount of schedulers online. Valid range is .

Returns the old value of the flag.

@@ -4932,6 +4942,7 @@ true + All LevelEntrys of a list must contain the same LevelTag, except on the top level where both node and @@ -4956,7 +4967,7 @@ true of the current system (emulator) as specified by Item:

- cpu_topology + cpu_topology

Returns the CpuTopology which currently is used by the emulator. The CPU topology is used when binding schedulers @@ -6188,6 +6199,8 @@ true + + Trace information about a process or function

Returns trace information about a process or function.

diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam index c44f05f87d..01246a34da 100644 Binary files a/erts/preloaded/ebin/erlang.beam and b/erts/preloaded/ebin/erlang.beam differ diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index b1b2156ad5..65ebe83c3a 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -117,7 +117,7 @@ is_record/3, is_reference/1, is_tuple/1, load_module/2, load_nif/2, localtime_to_universaltime/2, make_fun/3, make_tuple/2, make_tuple/3, nodes/1, open_port/2, - port_call/3, port_info/1, port_info/2, process_flag/2, + port_call/2, port_call/3, port_info/1, port_info/2, process_flag/2, process_info/2, send/2, send/3, seq_trace_info/1, setelement/3, spawn_opt/1, statistics/1, subtract/2, system_flag/2, @@ -579,12 +579,14 @@ erase(_Key) -> erlang:nif_error(undefined). % error/1 +%% Shadowed by erl_bif_types: erlang:error/1 -spec error(Reason) -> no_return() when Reason :: term(). error(_Reason) -> erlang:nif_error(undefined). % error/2 +%% Shadowed by erl_bif_types: erlang:error/2 -spec error(Reason, Args) -> no_return() when Reason :: term(), Args :: [term()]. @@ -592,6 +594,7 @@ error(_Reason, _Args) -> erlang:nif_error(undefined). % exit/1 +%% Shadowed by erl_bif_types: erlang:exit/1 -spec exit(Reason) -> no_return() when Reason :: term(). exit(_Reason) -> @@ -719,11 +722,13 @@ group_leader(_GroupLeader, _Pid) -> erlang:nif_error(undefined). % halt/0 +%% Shadowed by erl_bif_types: erlang:halt/0 -spec halt() -> no_return(). halt() -> erlang:nif_error(undefined). % halt/1 +%% Shadowed by erl_bif_types: erlang:halt/1 -spec halt(Status) -> no_return() when Status :: non_neg_integer() | string(). halt(_Status) -> @@ -934,12 +939,14 @@ monitor_node(_Node, _Flag, _Options) -> erlang:nif_error(undefined). % nif_error/1 +%% Shadowed by erl_bif_types: erlang:nif_error/1 -spec erlang:nif_error(Reason) -> no_return() when Reason :: term(). nif_error(_Reason) -> erlang:nif_error(undefined). % nif_error/2 +%% Shadowed by erl_bif_types: erlang:nif_error/2 -spec erlang:nif_error(Reason, Args) -> no_return() when Reason :: term(), Args :: [term()]. @@ -1293,6 +1300,7 @@ system_profile(_ProfilerPid, _Options) -> erlang:nif_error(undefined). % throw/1 +%% Shadowed by erl_bif_types: erlang:throw/1 -spec throw(Any) -> no_return() when Any :: term(). throw(_Any) -> @@ -1380,6 +1388,7 @@ whereis(_RegName) -> %% types and specs +%% Shadowed by erl_bif_types: erlang:abs/1 -spec abs(Float) -> float() when Float :: float(); (Int) -> non_neg_integer() when @@ -1388,12 +1397,14 @@ abs(_Number) -> erlang:nif_error(undefined). %% Not documented +%% Shadowed by erl_bif_types: erlang:append/2 -spec erlang:append(List,Tail) -> maybe_improper_list() when List :: [term()], Tail :: term(). append(_List,_Tail) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:element/2 -spec element(N, Tuple) -> term() when N :: pos_integer(), Tuple :: tuple(). @@ -1408,6 +1419,7 @@ element(_N, _Tuple) -> get_module_info(_Module, _Item) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:hd/1 -spec hd(List) -> term() when List :: [term(), ...]. hd(_List) -> @@ -1415,73 +1427,87 @@ hd(_List) -> %% erlang:info/1 no longer exists! +%% Shadowed by erl_bif_types: erlang:is_atom/1 -spec is_atom(Term) -> boolean() when Term :: term(). is_atom(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_binary/1 -spec is_binary(Term) -> boolean() when Term :: term(). is_binary(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_bitstring/1 -spec is_bitstring(Term) -> boolean() when Term :: term(). is_bitstring(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_boolean/1 -spec is_boolean(Term) -> boolean() when Term :: term(). is_boolean(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_float/1 -spec is_float(Term) -> boolean() when Term :: term(). is_float(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_function/1 -spec is_function(Term) -> boolean() when Term :: term(). is_function(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_function/2 -spec is_function(Term, Arity) -> boolean() when Term :: term(), Arity :: arity(). is_function(_Term, _Arity) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_integer/1 -spec is_integer(Term) -> boolean() when Term :: term(). is_integer(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_list/1 -spec is_list(Term) -> boolean() when Term :: term(). is_list(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_number/1 -spec is_number(Term) -> boolean() when Term :: term(). is_number(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_pid/1 -spec is_pid(Term) -> boolean() when Term :: term(). is_pid(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_port/1 -spec is_port(Term) -> boolean() when Term :: term(). is_port(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_record/2 -spec is_record(Term,RecordTag) -> boolean() when Term :: term(), RecordTag :: atom(). is_record(_Term,_RecordTag) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_record/3 -spec is_record(Term,RecordTag,Size) -> boolean() when Term :: term(), RecordTag :: atom(), @@ -1489,11 +1515,13 @@ is_record(_Term,_RecordTag) -> is_record(_Term,_RecordTag,_Size) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_reference/1 -spec is_reference(Term) -> boolean() when Term :: term(). is_reference(_Term) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:is_tuple/1 -spec is_tuple(Term) -> boolean() when Term :: term(). is_tuple(_Term) -> @@ -1531,12 +1559,14 @@ localtime_to_universaltime(_Localtime, _IsDst) -> make_fun(_Module,_Function, _Arity) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:make_tuple/2 -spec erlang:make_tuple(Arity, InitialValue) -> tuple() when Arity :: arity(), InitialValue :: term(). make_tuple(_Arity,_InitialValue) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:make_tuple/3 -spec erlang:make_tuple(Arity, DefaultValue, InitList) -> tuple() when Arity :: arity(), DefaultValue :: term(), @@ -1575,6 +1605,14 @@ nodes(_Arg) -> open_port(_PortName,_PortSettings) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:port_call/2 +-spec erlang:port_call(Port, Data) -> term() when + Port :: port() | atom(), + Data :: term(). +port_call(_Port, _Data) -> + erlang:nif_error(undefined). + +%% Shadowed by erl_bif_types: erlang:port_call/3 -spec erlang:port_call(Port, Operation, Data) -> term() when Port :: port() | atom(), Operation :: integer(), @@ -1600,16 +1638,18 @@ port_call(_Port, _Operation, _Data) -> {input, Bytes :: non_neg_integer()} | {output, Bytes :: non_neg_integer()}. +%% Shadowed by erl_bif_types: erlang:port_info/1 -spec erlang:port_info(Port) -> Result when Port :: port() | atom(), Result :: [port_info_result_item()] | undefined. port_info(_Result) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:port_info/2 -spec erlang:port_info(Port, Item) -> Result when Port :: port() | atom(), Item :: port_info_item(), - Result :: port_info_result_item() | undefined | []. + Result :: port_info_result_item() | undefined. port_info(_Result, _Item) -> erlang:nif_error(undefined). @@ -1689,7 +1729,7 @@ process_flag(_Flag, _Value) -> {current_location, {Module :: module(), Function :: atom(), Arity :: arity(), Location :: [{file, Filename :: string()} | % not a stack_item()! - {line, Line :: integer()}]}} | + {line, Line :: pos_integer()}]}} | {current_stacktrace, Stack :: [stack_item()]} | {dictionary, Dictionary :: [{Key :: term(), Value :: term()}]} | {error_handler, Module :: module()} | @@ -1728,7 +1768,7 @@ process_flag(_Flag, _Value) -> Function :: atom(), Arity :: arity() | (Args :: [term()]), Location :: [{file, Filename :: string()} | - {line, Line :: integer()}]}. + {line, Line :: pos_integer()}]}. -spec process_info(Pid, Item) -> InfoTuple | [] | undefined when @@ -1744,7 +1784,7 @@ process_flag(_Flag, _Value) -> process_info(_Pid,_ItemSpec) -> erlang:nif_error(undefined). --spec send(Dest, Msg) -> Msg when +-spec erlang:send(Dest, Msg) -> Msg when Dest :: dst(), Msg :: term(). send(_Dest,_Msg) -> @@ -1768,6 +1808,7 @@ send(_Dest,_Msg,_Options) -> seq_trace_info(_What) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:setelement/3 -spec setelement(Index, Tuple1, Value) -> Tuple2 when Index :: pos_integer(), Tuple1 :: tuple(), @@ -1817,6 +1858,7 @@ statistics(_Item) -> erlang:nif_error(undefined). %% Not documented +%% Shadowed by erl_bif_types: erlang:subtract/2 -spec erlang:subtract([term()], [term()]) -> [term()]. subtract(_,_) -> erlang:nif_error(undefined). @@ -1881,6 +1923,7 @@ term_to_binary(_Term) -> term_to_binary(_Term, _Options) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:tl/1 -spec tl(List) -> term() when List :: [term(), ...]. tl(_List) -> @@ -1916,6 +1959,7 @@ trace_pattern(_MFA, _MatchSpec) -> trace_pattern(_MFA, _MatchSpec, _FlagList) -> erlang:nif_error(undefined). +%% Shadowed by erl_bif_types: erlang:tuple_to_list/1 -spec tuple_to_list(Tuple) -> [term()] when Tuple :: tuple(). tuple_to_list(_Tuple) -> @@ -1934,6 +1978,7 @@ tuple_to_list(_Tuple) -> -type info_list() :: []. %% Note: changing the ordering number of a clause will change the docs! +%% Shadowed by erl_bif_types: erlang:system_info/1 -spec erlang:system_info (allocated_areas) -> [ tuple() ]; (allocator) -> @@ -2031,6 +2076,7 @@ universaltime_to_localtime(_Universaltime) -> apply(Fun, Args) -> erlang:apply(Fun, Args). +%% Shadowed by erl_bif_types: erlang:apply/3 -spec apply(Module, Function, Args) -> term() when Module :: module(), Function :: atom(), diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index 190f14a474..b822f182c2 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -63,6 +63,7 @@ t_fun/2, t_fun_args/1, t_fun_range/1, + t_identifier/0, t_inf/2, t_integer/0, t_integer/1, @@ -138,6 +139,12 @@ type(M, F, A) -> -spec type(atom(), atom(), arity(), [erl_types:erl_type()]) -> erl_types:erl_type(). %%-- erlang ------------------------------------------------------------------- +type(erlang, halt, 0, _) -> t_none(); +type(erlang, halt, 1, _) -> t_none(); +type(erlang, exit, 1, _) -> t_none(); +type(erlang, error, 1, _) -> t_none(); +type(erlang, error, 2, _) -> t_none(); +type(erlang, throw, 1, _) -> t_none(); type(erlang, '==', 2, Xs = [X1, X2]) -> case t_is_atom(X1) andalso t_is_atom(X2) of true -> type(erlang, '=:=', 2, Xs); @@ -489,6 +496,9 @@ type(erlang, 'bnot', 1, Xs) -> {ok, T} -> T end end); +%% Guard bif, needs to be here. +type(erlang, abs, 1, Xs) -> + strict(arg_types(erlang, abs, 1), Xs, fun ([X]) -> X end); %% This returns (-X)-1, so it often gives a negative result. %% strict(arg_types(erlang, 'bnot', 1), Xs, fun (_) -> t_integer() end); type(erlang, append, 2, Xs) -> type(erlang, '++', 2, Xs); % alias @@ -504,8 +514,24 @@ type(erlang, apply, 2, Xs) -> strict(arg_types(erlang, apply, 2), Xs, Fun); type(erlang, apply, 3, Xs) -> strict(arg_types(erlang, apply, 3), Xs, fun (_) -> t_any() end); +%% Guard bif, needs to be here. +type(erlang, binary_part, 2, Xs) -> + strict(arg_types(erlang, binary_part, 2), Xs, fun (_) -> t_binary() end); +%% Guard bif, needs to be here. +type(erlang, binary_part, 3, Xs) -> + strict(arg_types(erlang, binary_part, 3), Xs, fun (_) -> t_binary() end); +%% Guard bif, needs to be here. +type(erlang, bit_size, 1, Xs) -> + strict(arg_types(erlang, bit_size, 1), Xs, + fun (_) -> t_non_neg_integer() end); +%% Guard bif, needs to be here. +type(erlang, byte_size, 1, Xs) -> + strict(arg_types(erlang, byte_size, 1), Xs, + fun (_) -> t_non_neg_integer() end); type(erlang, disconnect_node, 1, Xs) -> strict(arg_types(erlang, disconnect_node, 1), Xs, fun (_) -> t_sup([t_boolean(), t_atom('ignored')]) end); +%% Guard bif, needs to be here. +%% Also much more expressive than anything you could write in a spec... type(erlang, element, 2, Xs) -> strict(arg_types(erlang, element, 2), Xs, fun ([X1, X2]) -> @@ -529,16 +555,22 @@ type(erlang, element, 2, Xs) -> t_sup([type(erlang, element, 2, [X1, Y]) || Y <- Ts]) end end); +%% Guard bif, needs to be here. +type(erlang, float, 1, Xs) -> + strict(arg_types(erlang, float, 1), Xs, fun (_) -> t_float() end); type(erlang, fun_info, 1, Xs) -> strict(arg_types(erlang, fun_info, 1), Xs, fun (_) -> t_list(t_tuple([t_atom(), t_any()])) end); type(erlang, get_cookie, 0, _) -> t_atom(); % | t_atom('nocookie') +%% Guard bif, needs to be here. type(erlang, hd, 1, Xs) -> strict(arg_types(erlang, hd, 1), Xs, fun ([X]) -> t_cons_hd(X) end); type(erlang, integer_to_list, 2, Xs) -> strict(arg_types(erlang, integer_to_list, 2), Xs, fun (_) -> t_string() end); type(erlang, info, 1, Xs) -> type(erlang, system_info, 1, Xs); % alias +%% All type tests are guard BIF's and may be implemented in ways that +%% cannot be expressed in a type spec, why they are kept in erl_bif_types. type(erlang, is_atom, 1, Xs) -> Fun = fun (X) -> check_guard(X, fun (Y) -> t_is_atom(Y) end, t_atom()) end, strict(arg_types(erlang, is_atom, 1), Xs, Fun); @@ -702,6 +734,9 @@ type(erlang, is_tuple, 1, Xs) -> check_guard(X, fun (Y) -> t_is_tuple(Y) end, t_tuple()) end, strict(arg_types(erlang, is_tuple, 1), Xs, Fun); +%% Guard bif, needs to be here. +type(erlang, length, 1, Xs) -> + strict(arg_types(erlang, length, 1), Xs, fun (_) -> t_non_neg_fixnum() end); type(erlang, list_to_integer, 2, Xs) -> strict(arg_types(erlang, list_to_integer, 2), Xs, fun (_) -> t_integer() end); @@ -726,12 +761,47 @@ type(erlang, nif_error, 1, _) -> t_any(); % this BIF and the next one are stubs for NIFs and never return type(erlang, nif_error, 2, Xs) -> strict(arg_types(erlang, nif_error, 2), Xs, fun (_) -> t_any() end); +%% Guard bif, needs to be here. +type(erlang, node, 0, _) -> t_node(); +%% Guard bif, needs to be here. +type(erlang, node, 1, Xs) -> + strict(arg_types(erlang, node, 1), Xs, fun (_) -> t_node() end); type(erlang, nodes, 0, _) -> t_list(t_node()); type(erlang, port_call, Arity, Xs) when Arity =:= 2; Arity =:= 3 -> strict(arg_types(erlang, port_call, Arity), Xs, fun (_) -> t_any() end); type(erlang, port_info, 1, Xs) -> strict(arg_types(erlang, port_info, 1), Xs, fun (_) -> t_sup(t_atom('undefined'), t_list()) end); +type(erlang, port_info, 2, Xs) -> + strict(arg_types(erlang, port_info, 2), Xs, + fun ([_Port, Item]) -> + t_sup(t_atom('undefined'), + case t_atom_vals(Item) of + ['connected'] -> t_tuple([Item, t_pid()]); + ['id'] -> t_tuple([Item, t_integer()]); + ['input'] -> t_tuple([Item, t_integer()]); + ['links'] -> t_tuple([Item, t_list(t_pid())]); + ['name'] -> t_tuple([Item, t_string()]); + ['output'] -> t_tuple([Item, t_integer()]); + ['registered_name'] -> t_tuple([Item, t_atom()]); + List when is_list(List) -> + t_tuple([t_sup([t_atom(A) || A <- List]), + t_sup([t_atom(), t_integer(), + t_pid(), t_list(t_pid()), + t_string()])]); + unknown -> + [_, PosItem] = arg_types(erlang, port_info, 2), + t_tuple([PosItem, + t_sup([t_atom(), t_integer(), + t_pid(), t_list(t_pid()), + t_string()])]) + end) + end); +%% Guard bif, needs to be here. +type(erlang, round, 1, Xs) -> + strict(arg_types(erlang, round, 1), Xs, fun (_) -> t_integer() end); +%% Guard bif, needs to be here. +type(erlang, self, 0, _) -> t_pid(); type(erlang, set_cookie, 2, Xs) -> strict(arg_types(erlang, set_cookie, 2), Xs, fun (_) -> t_atom('true') end); type(erlang, setelement, 3, Xs) -> @@ -765,6 +835,9 @@ type(erlang, setelement, 3, Xs) -> t_sup([type(erlang, setelement, 3, [X1, Y, X3]) || Y <- Ts]) end end); +%% Guard bif, needs to be here. +type(erlang, size, 1, Xs) -> + strict(arg_types(erlang, size, 1), Xs, fun (_) -> t_non_neg_integer() end); type(erlang, spawn, 1, Xs) -> strict(arg_types(erlang, spawn, 1), Xs, fun (_) -> t_pid() end); type(erlang, spawn, 2, Xs) -> @@ -894,13 +967,15 @@ type(erlang, system_info, 1, Xs) -> t_any() %% overapproximation as the return value might change end end); -type(erlang, term_to_binary, 1, Xs) -> - strict(arg_types(erlang, term_to_binary, 1), Xs, fun (_) -> t_binary() end); +%% Guard bif, needs to be here. type(erlang, tl, 1, Xs) -> strict(arg_types(erlang, tl, 1), Xs, fun ([X]) -> t_cons_tl(X) end); -type(erlang, trace_pattern, 2, Xs) -> - strict(arg_types(erlang, trace_pattern, 2), Xs, - fun (_) -> t_non_neg_fixnum() end); %% num of MFAs that match pattern +%% Guard bif, needs to be here. +type(erlang, trunc, 1, Xs) -> + strict(arg_types(erlang, trunc, 1), Xs, fun (_) -> t_integer() end); +%% Guard bif, needs to be here. +type(erlang, tuple_size, 1, Xs) -> + strict(arg_types(erlang, tuple_size, 1), Xs, fun (_) -> t_non_neg_integer() end); type(erlang, tuple_to_list, 1, Xs) -> strict(arg_types(erlang, tuple_to_list, 1), Xs, fun ([X]) -> @@ -2092,6 +2167,9 @@ arg_types(erlang, 'bsl', 2) -> [t_integer(), t_integer()]; arg_types(erlang, 'bnot', 1) -> [t_integer()]; +%% Guard bif, needs to be here. +arg_types(erlang, abs, 1) -> + [t_number()]; arg_types(erlang, append, 2) -> arg_types(erlang, '++', 2); arg_types(erlang, apply, 2) -> @@ -2101,14 +2179,41 @@ arg_types(erlang, apply, 2) -> t_list()]; arg_types(erlang, apply, 3) -> [t_sup(t_atom(), t_tuple()), t_atom(), t_list()]; +%% Guard bif, needs to be here. +arg_types(erlang, binary_part, 2) -> + [t_binary(), t_tuple([t_non_neg_integer(), t_integer()])]; +%% Guard bif, needs to be here. +arg_types(erlang, binary_part, 3) -> + [t_binary(), t_non_neg_integer(), t_integer()]; +%% Guard bif, needs to be here. +arg_types(erlang, bit_size, 1) -> + [t_bitstr()]; +%% Guard bif, needs to be here. +arg_types(erlang, byte_size, 1) -> + [t_binary()]; arg_types(erlang, disconnect_node, 1) -> [t_node()]; +arg_types(erlang, halt, 0) -> + []; +arg_types(erlang, halt, 1) -> + [t_sup(t_non_neg_fixnum(), t_string())]; +arg_types(erlang, error, 1) -> + [t_any()]; +arg_types(erlang, error, 2) -> + [t_any(), t_list()]; +arg_types(erlang, exit, 1) -> + [t_any()]; +%% Guard bif, needs to be here. arg_types(erlang, element, 2) -> [t_pos_fixnum(), t_tuple()]; +%% Guard bif, needs to be here. +arg_types(erlang, float, 1) -> + [t_number()]; arg_types(erlang, fun_info, 1) -> [t_fun()]; arg_types(erlang, get_cookie, 0) -> []; +%% Guard bif, needs to be here. arg_types(erlang, hd, 1) -> [t_cons()]; arg_types(erlang, info, 1) -> @@ -2149,6 +2254,9 @@ arg_types(erlang, is_reference, 1) -> [t_any()]; arg_types(erlang, is_tuple, 1) -> [t_any()]; +%% Guard bif, needs to be here. +arg_types(erlang, length, 1) -> + [t_list()]; arg_types(erlang, list_to_integer, 2) -> [t_list(t_byte()), t_from_range(2, 36)]; arg_types(erlang, make_tuple, 2) -> @@ -2161,6 +2269,12 @@ arg_types(erlang, nif_error, 1) -> [t_any()]; arg_types(erlang, nif_error, 2) -> [t_any(), t_list()]; +%% Guard bif, needs to be here. +arg_types(erlang, node, 0) -> + []; +%% Guard bif, needs to be here. +arg_types(erlang, node, 1) -> + [t_identifier()]; arg_types(erlang, nodes, 0) -> []; arg_types(erlang, port_call, 2) -> @@ -2169,10 +2283,23 @@ arg_types(erlang, port_call, 3) -> [t_sup(t_port(), t_atom()), t_integer(), t_any()]; arg_types(erlang, port_info, 1) -> [t_sup(t_port(), t_atom())]; +arg_types(erlang, port_info, 2) -> + [t_sup(t_port(), t_atom()), + t_atoms(['registered_name', 'id', 'connected', + 'links', 'name', 'input', 'output'])]; +%% Guard bif, needs to be here. +arg_types(erlang, round, 1) -> + [t_number()]; +%% Guard bif, needs to be here. +arg_types(erlang, self, 0) -> + []; arg_types(erlang, set_cookie, 2) -> [t_node(), t_atom()]; arg_types(erlang, setelement, 3) -> [t_pos_integer(), t_tuple(), t_any()]; +%% Guard bif, needs to be here. +arg_types(erlang, size, 1) -> + [t_sup(t_tuple(), t_binary())]; arg_types(erlang, spawn, 1) -> %% TODO: Tuple? [t_fun()]; arg_types(erlang, spawn, 2) -> %% TODO: Tuple? @@ -2194,14 +2321,17 @@ arg_types(erlang, system_info, 1) -> t_tuple([t_atom(), t_any()]), % documented t_tuple([t_atom(), t_atom(), t_any()]), t_tuple([t_atom(allocator_sizes), t_reference(), t_any()])])]; -arg_types(erlang, term_to_binary, 1) -> +arg_types(erlang, throw, 1) -> [t_any()]; +%% Guard bif, needs to be here. arg_types(erlang, tl, 1) -> [t_cons()]; -arg_types(erlang, trace_pattern, 2) -> - [t_sup(t_tuple([t_atom(), t_atom(), t_sup(t_arity(), t_atom('_'))]), - t_atom('on_load')), - t_sup([t_boolean(), t_list(), t_atom('restart'), t_atom('pause')])]; +%% Guard bif, needs to be here. +arg_types(erlang, trunc, 1) -> + [t_number()]; +%% Guard bif, needs to be here. +arg_types(erlang, tuple_size, 1) -> + [t_tuple()]; arg_types(erlang, tuple_to_list, 1) -> [t_tuple()]; arg_types(erlang, yield, 0) -> -- cgit v1.2.3