diff options
Diffstat (limited to 'lib/stdlib')
26 files changed, 595 insertions, 164 deletions
diff --git a/lib/stdlib/doc/src/binary.xml b/lib/stdlib/doc/src/binary.xml index 88ce77e0d0..7ce2defb72 100644 --- a/lib/stdlib/doc/src/binary.xml +++ b/lib/stdlib/doc/src/binary.xml @@ -505,7 +505,7 @@ <type> <v>Subject = binary()</v> <v>Pos = integer() >= 0</v> - <v>Len = integer() >= 0</v> + <v>Len = integer()</v> </type> <desc> <p>The same as <c>part(Subject, {Pos, Len})</c>.</p> diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index 667d758e29..e6d262466c 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -70,7 +70,7 @@ <desc> <p>Either <c>standard_io</c>, <c>standard_error</c>, a registered name, or a pid handling IO protocols (returned from - <seealso marker="file#open/2">file:open/2</seealso>).</p> + <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p> </desc> </datatype> <datatype> diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml index f81f8bda96..ad5f8bd5ac 100644 --- a/lib/stdlib/doc/src/ms_transform.xml +++ b/lib/stdlib/doc/src/ms_transform.xml @@ -308,7 +308,7 @@ ets:select(emp_tab, ets:fun2ms( Erlang code. Also arithmetics is allowed, as well as ordinary guard bif's. Here's a list of bif's and expressions:</p> <list type="bulleted"> - <item>The type tests: is_atom, is_constant, is_float, is_integer, + <item>The type tests: is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function, is_record</item> <item>The boolean operators: not, and, or, andalso, orelse </item> @@ -318,7 +318,7 @@ ets:select(emp_tab, ets:fun2ms( <item>The guard bif's: abs, element, hd, length, node, round, size, tl, trunc, self</item> <item>The obsolete type test (only in guards): - atom, constant, float, integer, + atom, float, integer, list, number, pid, port, reference, tuple, binary, function, record</item> </list> diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index d9c220b996..42a26ee44a 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -30,6 +30,297 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 1.18</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Improved algorithm in module <c>random</c>. Avoid seed + values that are even divisors of the primes and by that + prevent getting sub-seeds that are stuck on zero. Worst + case was random:seed(0,0,0) that produced a series of + only zeros. This is an incompatible change in the sense + that applications that relies on reproducing a specific + series for a given seed will fail. The pseudo random + output is still deterministic but different compared to + earlier versions.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-8713</p> + </item> + <item> + <p> Calls to <c>global:whereis_name/1</c> have been + substituted for calls to + <c>global:safe_whereis_name/1</c> since the latter is not + safe at all.</p> + <p>The reason for not doing this earlier is that setting + a global lock masked out a bug concerning the restart of + supervised children. The bug has now been fixed by a + modification of <c>global:whereis_name/1</c>. (Thanks to + Ulf Wiger for code contribution.)</p> + <p>A minor race conditions in <c>gen_fsm:start*</c> has + been fixed: if one of these functions returned <c>{error, + Reason}</c> or ignore, the name could still be registered + (either locally or in <c>global</c>. (This is the same + modification as was done for gen_server in OTP-7669.)</p> + <p>The undocumented function + <c>global:safe_whereis_name/1</c> has been removed. </p> + <p> + Own Id: OTP-9212 Aux Id: seq7117, OTP-4174 </p> + </item> + <item> + <p> + If a child of a supervisor terminates with reason + {shutdown,Term} it is now handled by the supervisor as if + the reason was 'shutdown'. </p> + <p> + For children with restart type 'permanent', this implies + no change. For children with restart type 'transient', + the child will no longer be restarted and no supervisor + report will be written. For children with restart type + 'temporary', no supervisor report will be written.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9222</p> + </item> + <item> + <p> + Minor improvement of documentation regarding supervisor + restart strategy for temporary and transient child + processes.</p> + <p> + Own Id: OTP-9381</p> + </item> + <item> + <p>A Dets table with sufficiently large buckets could not + always be repaired. This bug has been fixed. </p> <p>The + format of Dets files has been modified. When downgrading + tables created with the new system will be repaired. + Otherwise the modification should not be noticeable. </p> + <p> + Own Id: OTP-9607</p> + </item> + <item> + <p> A few contracts in the <c>lists</c> module have been + corrected. </p> + <p> + Own Id: OTP-9616</p> + </item> + <item> + <p> + Add '-callback' attributes in stdlib's behaviours</p> + <p> + Replace the behaviour_info(callbacks) export in stdlib's + behaviours with -callback' attributes for all the + callbacks. Update the documentation with information on + the callback attribute Automatically generate + 'behaviour_info' function from '-callback' attributes</p> + <p> + 'behaviour_info(callbacks)' is a special function that is + defined in a module which describes a behaviour and + returns a list of its callbacks.</p> + <p> + This function is now automatically generated using the + '-callback' specs. An error is returned by lint if user + defines both '-callback' attributes and the + behaviour_info/1 function. If no type info is needed for + a callback use a generic spec for it. Add '-callback' + attribute to language syntax</p> + <p> + Behaviours may define specs for their callbacks using the + familiar spec syntax, replacing the '-spec' keyword with + '-callback'. Simple lint checks are performed to ensure + that no callbacks are defined twice and all types + referred are declared.</p> + <p> + These attributes can be then used by tools to provide + documentation to the behaviour or find discrepancies in + the callback definitions in the callback module.</p> + <p> + Add callback specs into 'application' module in kernel + Add callback specs to tftp module following internet + documentation Add callback specs to inets_service module + following possibly deprecated comments</p> + <p> + Own Id: OTP-9621</p> + </item> + <item> + <p> If a Dets table had been properly closed but the + space management data could not been read, it was not + possible to repair the file. This bug has been fixed. + </p> + <p> + Own Id: OTP-9622</p> + </item> + <item> + <p> + The Unicode noncharacter code points 16#FFFE and 16#FFFE + were not allowed to be encoded or decoded using the + <c>unicode</c> module or bit syntax. That was + inconsistent with the other noncharacters 16#FDD0 to + 16#FDEF that could be encoded/decoded. To resolve the + inconsistency, 16#FFFE and 16#FFFE can now be encoded and + decoded. (Thanks to Alisdair Sullivan.)</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9624</p> + </item> + <item> + <p> + Make epp search directory of current file first when + including another file This completes a partial fix in + R11 that only worked for include_lib(). (Thanks to + Richard Carlsson)</p> + <p> + Own Id: OTP-9645</p> + </item> + <item> + <p> + ms_transform: Fix incorrect `variable shadowed' warnings</p> + <p> + This patch removes incorrect passing of variable bindings + from one function clause to another. (Thanks to Haitao + Li)</p> + <p> + Own Id: OTP-9646</p> + </item> + <item> + <p> + Explicitly kill dynamic children in supervisors</p> + <p> + According to the supervisor's documentation: "Important + note on simple-one-for-one supervisors: The dynamically + created child processes of a simple-one-for-one + supervisor are not explicitly killed, regardless of + shutdown strategy, but are expected to terminate when the + supervisor does (that is, when an exit signal from the + parent process is received)."</p> + <p> + All is fine as long as we stop simple_one_for_one + supervisor manually. Dynamic children catch the exit + signal from the supervisor and leave. But, if this + happens when we stop an application, after the top + supervisor has stopped, the application master kills all + remaining processes associated to this application. So, + dynamic children that trap exit signals can be killed + during their cleanup (here we mean inside terminate/2). + This is unpredictable and highly time-dependent.</p> + <p> + In this commit, supervisor module is patched to + explicitly terminate dynamic children accordingly to the + shutdown strategy.</p> + <p> + NOTE: Order in which dynamic children are stopped is not + defined. In fact, this is "almost" done at the same time.</p> + <p> + Stack errors when dynamic children are stopped</p> + <p> + Because a simple_one_for_one supervisor can have many + workers, we stack errors during its shutdown to report + only one message for each encountered error type. Instead + of reporting the child's pid, we use the number of + concerned children. (Thanks to Christopher Faulet)</p> + <p> + Own Id: OTP-9647</p> + </item> + <item> + <p> + Allow an infinite timeout to shutdown worker processes</p> + <p> + Now, in child specification, the shutdown value can also + be set to infinity for worker children. This restriction + was removed because this is not always possible to + predict the shutdown time for a worker. This is highly + application-dependent. Add a warning to docs about + workers' shutdown strategy (Thanks to Christopher Faulet)</p> + <p> + Own Id: OTP-9648</p> + </item> + <item> + <p> + A badarg would sometimes occur in supervisor when + printing error reports and the child pid was undefined. + This has been corrected.</p> + <p> + Own Id: OTP-9669</p> + </item> + <item> + <p> + Fix re:split spec not to accept option 'global'(Thanks to + Shunichi Shinohara)</p> + <p> + Own Id: OTP-9691</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Fix a few tests that used to fail on the HiPE + platform. </p> + <p> + Own Id: OTP-9637</p> + </item> + <item> + <p>Variables are now now allowed in '<c>fun M:F/A</c>' as + suggested by Richard O'Keefe in EEP-23.</p> + <p>The representation of '<c>fun M:F/A</c>' in the + abstract format has been changed in an incompatible way. + Tools that directly read or manipulate the abstract + format (such as parse transforms) may need to be updated. + The compiler can handle both the new and the old format + (i.e. extracting the abstract format from a pre-R15 BEAM + file and compiling it using compile:forms/1,2 will work). + The <c>syntax_tools</c> application can also handle both + formats.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9643</p> + </item> + <item> + <p> + Tuple funs (a two-element tuple with a module name and a + function) are now officially deprecated and will be + removed in R16. Use '<c>fun M:F/A</c>' instead. To make + you aware that your system uses tuple funs, the very + first time a tuple fun is applied, a warning will be sent + to the error logger.</p> + <p> + Own Id: OTP-9649</p> + </item> + <item> + <p> + The deprecated '<c>regexp</c>' module has been removed. + Use the '<c>re</c>' module instead.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-9737</p> + </item> + <item> + <p> + <c>filename:find_src/1,2</c> will now work on stripped + BEAM files (reported by Per Hedeland). The HiPE compiler + will also work on stripped BEAM files. The BEAM compiler + will no longer include compilation options given in the + source code itself in <c>M:module_info(compile)</c> + (because those options will be applied anyway if the + module is re-compiled).</p> + <p> + Own Id: OTP-9752</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 1.17.5</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/stdlib/doc/src/sofs.xml b/lib/stdlib/doc/src/sofs.xml index 2e7768a1df..37c41501ae 100644 --- a/lib/stdlib/doc/src/sofs.xml +++ b/lib/stdlib/doc/src/sofs.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2011</year> + <year>2001</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -317,7 +317,7 @@ but is to be preferred since it makes it possible to handle this case even more efficiently. Examples of SetFuns:</p> <pre> -{sofs, union} +fun sofs:union/1 fun(S) -> sofs:partition(1, S) end {external, fun(A) -> A end} {external, fun({A,_,C}) -> {C,A} end} @@ -711,7 +711,7 @@ fun(S) -> sofs:partition(1, S) end argument.</p> <pre> 1> <input>F1 = sofs:from_term([{a,[[1,2],[2,3]]},{b,[[]]}]),</input> -<input>F2 = sofs:family_projection({sofs, union}, F1),</input> +<input>F2 = sofs:family_projection(fun sofs:union/1, F1),</input> <input>sofs:to_external(F2).</input> [{a,[1,2,3]},{b,[]}]</pre> </desc> @@ -821,7 +821,7 @@ fun(S) -> sofs:partition(1, S) end <input>sofs:to_external(F2).</input> [{a,[1,2,3]},{b,[]}]</pre> <p><c>family_union(F)</c> is equivalent to - <c>family_projection({sofs,union}, F)</c>.</p> + <c>family_projection(fun sofs:union/1, F)</c>.</p> </desc> </func> <func> @@ -1438,7 +1438,7 @@ true</pre> 1> <input>R1 = sofs:relation([{a,1},{b,2}]),</input> <input>R2 = sofs:relation([{x,1},{x,2},{y,3}]),</input> <input>S1 = sofs:from_sets([R1,R2]),</input> -<input>S2 = sofs:specification({sofs,is_a_function}, S1),</input> +<input>S2 = sofs:specification(fun sofs:is_a_function/1, S1),</input> <input>sofs:to_external(S2).</input> [[{a,1},{b,2}]]</pre> </desc> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index cddb55e5c5..33a7f5bb6a 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -127,25 +127,18 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <p><c>StartFunc</c> defines the function call used to start the child process. It should be a module-function-arguments tuple <c>{M,F,A}</c> used as <c>apply(M,F,A)</c>.</p> - <p> <br></br> -</p> <p>The start function <em>must create and link to</em> the child process, and should return <c>{ok,Child}</c> or <c>{ok,Child,Info}</c> where <c>Child</c> is the pid of the child process and <c>Info</c> an arbitrary term which is ignored by the supervisor.</p> - <p> <br></br> -</p> <p>The start function can also return <c>ignore</c> if the child process for some reason cannot be started, in which case - the child specification will be kept by the supervisor but - the non-existing child process will be ignored.</p> - <p> <br></br> -</p> + the child specification will be kept by the supervisor + (unless it is a temporary child) but the non-existing child + process will be ignored.</p> <p>If something goes wrong, the function may also return an error tuple <c>{error,Error}</c>.</p> - <p> <br></br> -</p> <p>Note that the <c>start_link</c> functions of the different behaviour modules fulfill the above requirements.</p> </item> diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index bf3c7b3504..95ba6b1096 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -947,7 +947,6 @@ type_test(integer) -> is_integer; type_test(float) -> is_float; type_test(number) -> is_number; type_test(atom) -> is_atom; -type_test(constant) -> is_constant; type_test(list) -> is_list; type_test(tuple) -> is_tuple; type_test(pid) -> is_pid; diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 20fd247cea..1c69a131f9 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -452,8 +452,10 @@ conj([], _E) -> conj([{{Name,_Rp},L,R,Sz} | AL], E) -> NL = neg_line(L), T1 = {op,NL,'orelse', - {call,NL,{atom,NL,is_record},[R,{atom,NL,Name},{integer,NL,Sz}]}, - {atom,NL,fail}}, + {call,NL, + {remote,NL,{atom,NL,erlang},{atom,NL,is_record}}, + [R,{atom,NL,Name},{integer,NL,Sz}]}, + {atom,NL,fail}}, T2 = case conj(AL, none) of empty -> T1; C -> {op,NL,'and',C,T1} @@ -581,7 +583,9 @@ strict_get_record_field(Line, R, {atom,_,F}=Index, Name, St0) -> ExpRp = erl_lint:modify_line(ExpR, fun(_L) -> 0 end), RA = {{Name,ExpRp},Line,ExpR,length(Fs)+1}, St2 = St1#exprec{strict_ra = [RA | St1#exprec.strict_ra]}, - {{call,Line,{atom,Line,element},[I,ExpR]},St2} + {{call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,ExpR]},St2} end. record_pattern(I, I, Var, Sz, Line, Acc) -> @@ -593,7 +597,9 @@ record_pattern(_, _, _, _, _, Acc) -> reverse(Acc). sloppy_get_record_field(Line, R, Index, Name, St) -> Fs = record_fields(Name, St), I = index_expr(Line, Index, Name, Fs), - expr({call,Line,{atom,Line,element},[I,R]}, St). + expr({call,Line, + {remote,Line,{atom,Line,erlang},{atom,Line,element}}, + [I,R]}, St). strict_record_tests([strict_record_tests | _]) -> true; strict_record_tests([no_strict_record_tests | _]) -> false; @@ -710,7 +716,8 @@ record_setel(R, Name, Fs, Us0) -> {'case',Lr,R, [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Wildcards]}],[], [foldr(fun ({I,Lf,Val}, Acc) -> - {call,Lf,{atom,Lf,setelement},[I,Acc,Val]} end, + {call,Lf,{remote,Lf,{atom,Lf,erlang}, + {atom,Lf,setelement}},[I,Acc,Val]} end, R, Us)]}, {clause,NLr,[{var,NLr,'_'}],[], [call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]}]}. diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index e5adb84932..a1af0057ca 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1804,12 +1804,19 @@ guard_test(G, Vt, St0) -> %% Specially handle record type test here. guard_test2({call,Line,{atom,Lr,record},[E,A]}, Vt, St0) -> gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Vt, St0); -guard_test2({call,_Line,{atom,_La,F},As}=G, Vt, St0) -> +guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) -> {Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this. A = length(As), case erl_internal:type_test(F, A) of - true when F =/= is_record -> {Asvt,St1}; - _ -> gexpr(G, Vt, St0) + true when F =/= is_record, A =/= 2 -> + case no_guard_bif_clash(St1, {F,A}) of + false -> + {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; + true -> + {Asvt,St1} + end; + _ -> + gexpr(G, Vt, St0) end; guard_test2(G, Vt, St) -> %% Everything else is a guard expression. @@ -1865,9 +1872,15 @@ gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) -> gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, Vt, St0) -> gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); -gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,_,_Name},{integer,_,_}]}, +gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]}, Vt, St0) -> - gexpr(E, Vt, St0); + {E,St1} = gexpr(E0, Vt, St0), + case no_guard_bif_clash(St0, {is_record,3}) of + true -> + {E,St1}; + false -> + {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)} + end; gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) -> {Asvt,St1} = gexpr_list(Asvt0, Vt, St0), {Asvt,add_error(Line, illegal_guard_expr, St1)}; @@ -3423,17 +3436,11 @@ obsolete_guard({call,Line,{atom,Lr,F},As}, St0) -> false -> deprecated_function(Line, erlang, F, As, St0); true -> - St1 = case F of - constant -> - deprecated_function(Lr, erlang, is_constant, As, St0); - _ -> - St0 - end, - case is_warn_enabled(obsolete_guard, St1) of + case is_warn_enabled(obsolete_guard, St0) of true -> - add_warning(Lr,{obsolete_guard, {F, Arity}}, St1); + add_warning(Lr,{obsolete_guard, {F, Arity}}, St0); false -> - St1 + St0 end end; obsolete_guard(_G, St) -> diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl index ee4f0b3a51..08f1873803 100644 --- a/lib/stdlib/src/error_logger_file_h.erl +++ b/lib/stdlib/src/error_logger_file_h.erl @@ -104,7 +104,7 @@ code_change(_OldVsn, State, _Extra) -> %%% ------------------------------------------------------ tag_event(Event) -> - {erlang:localtime(), Event}. + {erlang:universaltime(), Event}. write_events(Fd, Events) -> write_events1(Fd, lists:reverse(Events)). @@ -169,23 +169,18 @@ write_event(_, _) -> maybe_utc(Time) -> UTC = case application:get_env(sasl, utc_log) of - {ok, Val} -> - Val; + {ok, Val} -> Val; undefined -> %% Backwards compatible: case application:get_env(stdlib, utc_log) of - {ok, Val} -> - Val; - undefined -> - false + {ok, Val} -> Val; + undefined -> false end end, - if - UTC =:= true -> - {utc, calendar:local_time_to_universal_time(Time)}; - true -> - Time - end. + maybe_utc(Time, UTC). + +maybe_utc(Time, true) -> {utc, Time}; +maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}. format_report(Rep) when is_list(Rep) -> case string_p(Rep) of @@ -238,7 +233,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT"). write_time({utc,{{Y,Mo,D},{H,Mi,S}}}, Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); -write_time({{Y,Mo,D},{H,Mi,S}}, Type) -> +write_time({local, {{Y,Mo,D},{H,Mi,S}}}, Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl index fa13fbb2bd..48e069a407 100644 --- a/lib/stdlib/src/error_logger_tty_h.erl +++ b/lib/stdlib/src/error_logger_tty_h.erl @@ -97,7 +97,7 @@ set_group_leader() -> end. tag_event(Event) -> - {erlang:localtime(), Event}. + {erlang:universaltime(), Event}. write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod). @@ -162,23 +162,18 @@ write_event({_Time, _Error},_IOMod) -> maybe_utc(Time) -> UTC = case application:get_env(sasl, utc_log) of - {ok, Val} -> - Val; + {ok, Val} -> Val; undefined -> %% Backwards compatible: case application:get_env(stdlib, utc_log) of - {ok, Val} -> - Val; - undefined -> - false + {ok, Val} -> Val; + undefined -> false end end, - if - UTC =:= true -> - {utc, calendar:local_time_to_universal_time(Time)}; - true -> - Time - end. + maybe_utc(Time, UTC). + +maybe_utc(Time, true) -> {utc, Time}; +maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}. format(IOMod, String) -> format(IOMod, String, []). format(io_lib, String, Args) -> io_lib:format(String, Args); @@ -234,7 +229,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT"). write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); -write_time({{Y,Mo,D},{H,Mi,S}},Type) -> +write_time({local, {{Y,Mo,D},{H,Mi,S}}},Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). diff --git a/lib/stdlib/src/gen_fsm.erl b/lib/stdlib/src/gen_fsm.erl index 57734a075c..80866c0806 100644 --- a/lib/stdlib/src/gen_fsm.erl +++ b/lib/stdlib/src/gen_fsm.erl @@ -320,7 +320,7 @@ name_to_pid(Name) -> undefined -> case global:whereis_name(Name) of undefined -> - exit(could_not_find_registerd_name); + exit(could_not_find_registered_name); Pid -> Pid end; diff --git a/lib/stdlib/src/gen_server.erl b/lib/stdlib/src/gen_server.erl index af07bc988a..f720ec15f5 100644 --- a/lib/stdlib/src/gen_server.erl +++ b/lib/stdlib/src/gen_server.erl @@ -844,7 +844,7 @@ name_to_pid(Name) -> undefined -> case global:whereis_name(Name) of undefined -> - exit(could_not_find_registerd_name); + exit(could_not_find_registered_name); Pid -> Pid end; diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl index 63b397f3a5..4389fd457c 100644 --- a/lib/stdlib/src/ms_transform.erl +++ b/lib/stdlib/src/ms_transform.erl @@ -881,7 +881,6 @@ translate_language_element(Atom) -> end. old_bool_test(atom,1) -> is_atom; -old_bool_test(constant,1) -> is_constant; old_bool_test(float,1) -> is_float; old_bool_test(integer,1) -> is_integer; old_bool_test(list,1) -> is_list; @@ -896,7 +895,6 @@ old_bool_test(record,2) -> is_record; old_bool_test(_,_) -> undefined. bool_test(is_atom,1) -> true; -bool_test(is_constant,1) -> true; bool_test(is_float,1) -> true; bool_test(is_integer,1) -> true; bool_test(is_list,1) -> true; diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 7bacc05ff2..b9fbef9ed0 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. 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 @@ -337,11 +337,11 @@ obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 -> %% Added in R14B03. obsolete_1(docb_gen, _, _) -> - {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; + {removed,"the DocBuilder application was removed in R15B"}; obsolete_1(docb_transform, _, _) -> - {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; + {removed,"the DocBuilder application was removed in R15B"}; obsolete_1(docb_xml_check, _, _) -> - {deprecated,"the DocBuilder application is deprecated (will be removed in R15B)"}; + {removed,"the DocBuilder application was removed in R15B"}; %% Added in R15B obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver -> @@ -350,10 +350,18 @@ obsolete_1(ssl, pid, 1) -> {deprecated,"deprecated (will be removed in R17); is no longer needed"}; obsolete_1(inviso, _, _) -> {deprecated,"the inviso application has been deprecated and will be removed in R16"}; + +%% Added in R15B01. +obsolete_1(gs, _, _) -> + {deprecated,"the gs application has been deprecated and will be removed in R16; use the wx application instead"}; +obsolete_1(ssh, sign_data, 2) -> + {deprecated,"deprecated (will be removed in R16A); use public_key:pem_decode/1, public_key:pem_entry_decode/1 " + "and public_key:sign/3 instead"}; +obsolete_1(ssh, verify_data, 3) -> + {deprecated,"deprecated (will be removed in R16A); use public_key:ssh_decode/1, and public_key:verify/4 instead"}; obsolete_1(_, _, _) -> no. - -spec is_snmp_agent_function(atom(), byte()) -> boolean(). is_snmp_agent_function(c, 1) -> true; diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 42ea42f42e..ac5b078c29 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -270,6 +270,8 @@ start_children(Children, SupName) -> start_children(Children, [], SupName). start_children([Child|Chs], NChildren, SupName) -> case do_start_child(SupName, Child) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + start_children(Chs, NChildren, SupName); {ok, Pid} -> start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName); {ok, Pid, _Extra} -> @@ -325,6 +327,8 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) -> #child{mfargs = {M, F, A}} = Child, Args = A ++ EArgs, case do_start_child_i(M, F, Args) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + {reply, {ok, undefined}, State}; {ok, Pid} -> NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State), {reply, {ok, Pid}, NState}; @@ -611,12 +615,12 @@ handle_start_child(Child, State) -> case get_child(Child#child.name, State) of false -> case do_start_child(State#state.name, Child) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + {{ok, undefined}, State}; {ok, Pid} -> - {{ok, Pid}, - save_child(Child#child{pid = Pid}, State)}; + {{ok, Pid}, save_child(Child#child{pid = Pid}, State)}; {ok, Pid, Extra} -> - {{ok, Pid, Extra}, - save_child(Child#child{pid = Pid}, State)}; + {{ok, Pid, Extra}, save_child(Child#child{pid = Pid}, State)}; {error, What} -> {{error, {What, Child}}, State} end; diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index 369d8b224e..ca2f18a05a 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1167,15 +1167,22 @@ do_funs(LFH, EFH) -> [[[0]]], ['F'], LFH, EFH), %% Tests for a bug found by the Dialyzer - used to crash. - ?line check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end, - "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.", - 47, - ['Pmod'], LFH, EFH), - ?line check(fun() -> Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end, - "begin Pmod = erl_eval_helper:new(42), B = Pmod:add(7), B end.", - 49, - ['B','Pmod'], LFH, EFH), - + case test_server:is_native(erl_eval) of + true -> + %% Parameterized modules are not supported by HiPE. + ok; + false -> + check(fun() -> Pmod = erl_eval_helper:new(42), Pmod:add(5) end, + "begin Pmod = erl_eval_helper:new(42), Pmod:add(5) end.", + 47, + ['Pmod'], LFH, EFH), + check(fun() -> Pmod = erl_eval_helper:new(42), + B = Pmod:add(7), B end, + "begin Pmod = erl_eval_helper:new(42), " + "B = Pmod:add(7), B end.", + 49, + ['B','Pmod'], LFH, EFH) + end, ok. count_down(F, N) when N > 0 -> diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl index f8c1ad783c..8b162cfda0 100644 --- a/lib/stdlib/test/erl_expand_records_SUITE.erl +++ b/lib/stdlib/test/erl_expand_records_SUITE.erl @@ -178,6 +178,9 @@ expr(Config) when is_list(Config) -> true -> not_ok end. + + is_record(_, _, _) -> + error(wrong_is_record). ">> ], @@ -366,6 +369,8 @@ strict(Config) when is_list(Config) -> end catch error:_ -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts1, [strict_record_tests]), @@ -380,6 +385,8 @@ strict(Config) when is_list(Config) -> case foo of _ when A#r2.a =:= 1 -> ok end. + element(_, _) -> + error(wrong_element). ">> ], ?line run(Config, Ts2, [no_strict_record_tests]), @@ -415,6 +422,11 @@ update(Config) when is_list(Config) -> t2() -> R0 = #r{}, #r{_ = R0#r{a = ok}}. + + %% Implicit calls to setelement/3 must go to the BIF, + %% not to this function. + setelement(_, _, _) -> + erlang:error(wrong_setelement_called). ">> ], ?line run(Config, Ts), diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 9041adbe5c..4e93f056ad 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2631,7 +2631,35 @@ bif_clash(Config) when is_list(Config) -> binary_part(A,B,C). ">>, [warn_unused_import], - {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}} + {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, + %% Don't accept call to a guard BIF if there is a local definition + %% or an import with the same name. Note: is_record/2 is an + %% exception, since it is more of syntatic sugar than a real BIF. + {clash21, + <<"-export([is_list/1]). + -import(x, [is_tuple/1]). + -record(r, {a,b}). + x(T) when is_tuple(T) -> ok; + x(T) when is_list(T) -> ok. + y(T) when is_tuple(T) =:= true -> ok; + y(T) when is_list(T) =:= true -> ok; + y(T) when is_record(T, r, 3) -> ok; + y(T) when is_record(T, r, 3) =:= true -> ok; + y(T) when is_record(T, r) =:= true -> ok. + is_list(_) -> + ok. + is_record(_, _) -> + ok. + is_record(_, _, _) -> + ok. + ">>, + [{no_auto_import,[{is_tuple,1}]}], + {errors,[{4,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {5,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {6,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {7,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {8,erl_lint,{illegal_guard_local_call,{is_record,3}}}, + {9,erl_lint,{illegal_guard_local_call,{is_record,3}}}],[]}} ], ?line [] = run(Config, Ts), diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 0e8849b5b3..101828fdef 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -74,7 +74,7 @@ -export([bad_table/1, types/1]). -export([otp_9423/1]). --export([init_per_testcase/2]). +-export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing -export([random_test/0]). @@ -2385,6 +2385,8 @@ setopts_do(Opts) -> ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})), ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)), ?line ets:delete(T), + unlink(Heir), + exit(Heir, bang), ok. bad_table(doc) -> ["All kinds of operations with bad table argument"]; @@ -5645,7 +5647,8 @@ spawn_logger(Procs) -> true -> exit(Proc, kill); _ -> ok end, - erlang:display(process_info(Proc)), + erlang:display({"Waiting for 'DOWN' from", Proc, + process_info(Proc), pid_status(Proc)}), receive {'DOWN', Mon, _, _, _} -> ok @@ -5656,6 +5659,15 @@ spawn_logger(Procs) -> spawn_logger([From]) end. +pid_status(Pid) -> + try + erts_debug:get_internal_state({process_status, Pid}) + catch + error:undef -> + erts_debug:set_internal_state(available_internal_state, true), + pid_status(Pid) + end. + start_spawn_logger() -> case whereis(ets_test_spawn_logger) of Pid when is_pid(Pid) -> true; diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl index c9688354b1..a17307b07b 100644 --- a/lib/stdlib/test/ms_transform_SUITE.erl +++ b/lib/stdlib/test/ms_transform_SUITE.erl @@ -455,7 +455,6 @@ old_guards(Config) when is_list(Config) -> ?line setup(Config), Tests = [ {atom,is_atom}, - {constant,is_constant}, {float,is_float}, {integer,is_integer}, {list,is_list}, @@ -490,7 +489,6 @@ old_guards(Config) when is_list(Config) -> ?line [{'$1',[{is_integer,'$1'}, {is_float,'$1'}, {is_atom,'$1'}, - {is_constant,'$1'}, {is_list,'$1'}, {is_number,'$1'}, {is_pid,'$1'}, @@ -502,7 +500,7 @@ old_guards(Config) when is_list(Config) -> [true]}] = compile_and_run(RD, << "ets:fun2ms(fun(X) when integer(X)," - "float(X), atom(X), constant(X)," + "float(X), atom(X)," "list(X), number(X), pid(X)," "port(X), reference(X), tuple(X)," "binary(X), record(X,a) -> true end)" @@ -530,7 +528,6 @@ autoimported(Config) when is_list(Config) -> {self,0}, %{float,1}, see float_1_function/1 {is_atom,1}, - {is_constant,1}, {is_float,1}, {is_integer,1}, {is_list,1}, diff --git a/lib/stdlib/test/re_SUITE.erl b/lib/stdlib/test/re_SUITE.erl index 3b2e637c84..d6d946a28f 100644 --- a/lib/stdlib/test/re_SUITE.erl +++ b/lib/stdlib/test/re_SUITE.erl @@ -445,9 +445,17 @@ split_specials(Config) when is_list(Config) -> ok. -error_handling(doc) -> - ["Test that errors are handled correctly by the erlang code."]; -error_handling(Config) when is_list(Config) -> +%% Test that errors are handled correctly by the erlang code. +error_handling(_Config) -> + case test_server:is_native(re) of + true -> + %% Exceptions from native code look too different. + {skip,"re is native"}; + false -> + error_handling() + end. + +error_handling() -> % This test checks the exception tuples manufactured in the erlang % code to hide the trapping from the user at least when it comes to errors Dog = ?t:timetrap(?t:minutes(1)), @@ -455,14 +463,14 @@ error_handling(Config) when is_list(Config) -> % the trap to re:grun from grun, in the grun function clause % that handles precompiled expressions ?line {'EXIT',{badarg,[{re,run,["apa",{1,2,3,4},[global]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:run("apa",{1,2,3,4},[global])), % An invalid capture list will also cause a badarg late, % but with a non pre compiled RE, the exception should be thrown by the % grun function clause that handles RE's compiled implicitly by % the run/3 BIF before trapping. ?line {'EXIT',{badarg,[{re,run,["apa","p",[{capture,[1,{a}]},global]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:run("apa","p",[{capture,[1,{a}]},global])), % And so the case of a precompiled expression together with % a compile-option (binary and list subject): @@ -473,88 +481,88 @@ error_handling(Config) when is_list(Config) -> [<<"apa">>, {re_pattern,1,0,_}, [global,unicode]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:run(<<"apa">>,RE,[global,unicode])), ?line {'EXIT',{badarg,[{re,run, ["apa", {re_pattern,1,0,_}, [global,unicode]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:run("apa",RE,[global,unicode])), ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[])), ?line {'EXIT',{badarg,_}} = (catch re:run("apa","(p",[global])), % The replace errors: ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:replace("apa",{1,2,3,4},"X",[])), ?line {'EXIT',{badarg,[{re,replace,["apa",{1,2,3,4},"X",[global]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:replace("apa",{1,2,3,4},"X",[global])), ?line {'EXIT',{badarg,[{re,replace, ["apa", {re_pattern,1,0,_}, "X", [unicode]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:replace("apa",RE,"X",[unicode])), ?line <<"aXa">> = iolist_to_binary(re:replace("apa","p","X",[])), ?line {'EXIT',{badarg,[{re,replace, ["apa","p","X",[{capture,all,binary}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{capture,all,binary}]))), ?line {'EXIT',{badarg,[{re,replace, ["apa","p","X",[{capture,all}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{capture,all}]))), ?line {'EXIT',{badarg,[{re,replace, ["apa","p","X",[{return,banana}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch iolist_to_binary(re:replace("apa","p","X", [{return,banana}]))), ?line {'EXIT',{badarg,_}} = (catch re:replace("apa","(p","X",[])), % Badarg, not compile error. ?line {'EXIT',{badarg,[{re,replace, ["apa","(p","X",[{return,banana}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch iolist_to_binary(re:replace("apa","(p","X", [{return,banana}]))), % And the split errors: ?line [<<"a">>,<<"a">>] = (catch re:split("apa","p",[])), ?line [<<"a">>,<<"p">>,<<"a">>] = (catch re:split("apa",RE,[])), ?line {'EXIT',{badarg,[{re,split,["apa","p",[global]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa","p",[global])), ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa","p",[{capture,all}])), ?line {'EXIT',{badarg,[{re,split,["apa","p",[{capture,all,binary}]],_}, - {?MODULE, error_handling,1,_} | _]}} = + {?MODULE, error_handling,0,_} | _]}} = (catch re:split("apa","p",[{capture,all,binary}])), ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa",{1,2,3,4})), ?line {'EXIT',{badarg,[{re,split,["apa",{1,2,3,4},[]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa",{1,2,3,4},[])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, [unicode]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa",RE,[unicode])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, [{return,banana}]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa",RE,[{return,banana}])), ?line {'EXIT',{badarg,[{re,split, ["apa", RE, [banana]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa",RE,[banana])), ?line {'EXIT',{badarg,_}} = (catch re:split("apa","(p")), %Exception on bad argument, not compilation error @@ -562,7 +570,7 @@ error_handling(Config) when is_list(Config) -> ["apa", "(p", [banana]],_}, - {?MODULE,error_handling,1,_} | _]}} = + {?MODULE,error_handling,0,_} | _]}} = (catch re:split("apa","(p",[banana])), ?t:timetrap_cancel(Dog), ok. diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index b6019b86f0..a881742f13 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -2388,13 +2388,28 @@ otp_6554(Config) when is_list(Config) -> comm_err(<<"V = lists:seq(1, 20), case V of a -> ok end.">>), ?line "exception error: no function clause matching" = comm_err(<<"fun(P) when is_pid(P) -> true end(a).">>), - ?line "exception error: {function_clause," = - comm_err(<<"erlang:error(function_clause, [unproper | list]).">>), + case test_server:is_native(erl_eval) of + true -> + %% Native code has different exit reason. Don't bother + %% testing them. + ok; + false -> + "exception error: {function_clause," = + comm_err(<<"erlang:error(function_clause, " + "[unproper | list]).">>), + %% Cheating: + "exception error: no function clause matching " + "erl_eval:do_apply(4)" ++ _ = + comm_err(<<"erlang:error(function_clause, [4]).">>), + "exception error: no function clause matching " + "lists:reverse(" ++ _ = + comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>), + "exception error: no function clause matching " + "lists:reverse(34) (lists.erl, line " ++ _ = + comm_err(<<"lists:reverse(34).">>) + end, ?line "exception error: function_clause" = comm_err(<<"erlang:error(function_clause, 4).">>), - %% Cheating: - ?line "exception error: no function clause matching erl_eval:do_apply(4)" ++ _ = - comm_err(<<"erlang:error(function_clause, [4]).">>), ?line "exception error: no function clause matching" ++ _ = comm_err(<<"fun(a, b, c, d) -> foo end" " (lists:seq(1,17)," @@ -2404,10 +2419,6 @@ otp_6554(Config) when is_list(Config) -> ?line "exception error: no function clause matching" = comm_err(<<"fun(P, q) when is_pid(P) -> true end(a, b).">>), - ?line "exception error: no function clause matching lists:reverse(" ++ _ = - comm_err(<<"F=fun() -> hello end, lists:reverse(F).">>), - ?line "exception error: no function clause matching lists:reverse(34) (lists.erl, line " ++ _ = - comm_err(<<"lists:reverse(34).">>), ?line "exception error: no true branch found when evaluating an if expression" = comm_err(<<"if length([a,b]) > 17 -> a end.">>), ?line "exception error: no such process or port" = diff --git a/lib/stdlib/test/sofs_SUITE.erl b/lib/stdlib/test/sofs_SUITE.erl index 73b282149a..f11c6ec4d6 100644 --- a/lib/stdlib/test/sofs_SUITE.erl +++ b/lib/stdlib/test/sofs_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. 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 @@ -536,7 +536,7 @@ projection(Conf) when is_list(Conf) -> from_term([], [[atom]]))), ?line {'EXIT', {badarg, _}} = (catch projection({external, fun(X) -> X end}, from_term([[a]]))), - ?line eval(projection({sofs,union}, + ?line eval(projection(fun sofs:union/1, from_term([[[1,2],[2,3]], [[a,b],[b,c]]])), from_term([[1,2,3], [a,b,c]])), ?line eval(projection(fun(_) -> from_term([a]) end, @@ -628,7 +628,7 @@ substitution(Conf) when is_list(Conf) -> ?line {'EXIT', {badarg, _}} = (catch substitution({external, fun(X) -> X end}, from_term([[a]]))), ?line eval(substitution(fun(X) -> X end, from_term([], [[atom]])), E), - ?line eval(substitution({sofs,union}, + ?line eval(substitution(fun sofs:union/1, from_term([[[1,2],[2,3]], [[a,b],[b,c]]])), from_term([{[[1,2],[2,3]],[1,2,3]}, {[[a,b],[b,c]],[a,b,c]}])), ?line eval(substitution(fun(_) -> from_term([a]) end, @@ -745,7 +745,7 @@ restriction(Conf) when is_list(Conf) -> ?line eval(restriction(Id, S3, E), E), ?line eval(restriction(Id, from_term([], [[atom]]), set([a])), from_term([], [[atom]])), - ?line eval(restriction({sofs,union}, + ?line eval(restriction(fun sofs:union/1, from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]), from_term([[a,b],[1,2,3],[b,c]])), @@ -862,7 +862,7 @@ drestriction(Conf) when is_list(Conf) -> ?line eval(drestriction(Id, S3, E), S3), ?line eval(drestriction(Id, from_term([], [[atom]]), set([a])), from_term([], [[atom]])), - ?line eval(drestriction({sofs,union}, + ?line eval(drestriction(fun sofs:union/1, from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]), from_term([[a,b],[1,2,3],[b,c]])), @@ -1028,7 +1028,7 @@ specification(Conf) when is_list(Conf) -> end, ?line eval(specification({external,Fun2x}, S2), from_term([[1],[3]])), - Fun3 = fun(_) -> neither_true_or_false end, + Fun3 = fun(_) -> neither_true_nor_false end, ?line {'EXIT', {badarg, _}} = (catch specification(Fun3, set([a]))), ?line {'EXIT', {badarg, _}} = @@ -1810,8 +1810,8 @@ partition_3(Conf) when is_list(Conf) -> S12a = from_term([[[a],[b]], [[b],[c]], [[], [a,b]], [[1],[2]]]), S12b = from_term([[a,b],[1,2,3],[b,c]]), - ?line eval(partition({sofs,union}, S12a, S12b), - lpartition({sofs,union}, S12a, S12b)), + ?line eval(partition(fun sofs:union/1, S12a, S12b), + lpartition(fun sofs:union/1, S12a, S12b)), Fun13 = fun(_) -> from_term([a]) end, S13a = from_term([], [[atom]]), @@ -1879,12 +1879,9 @@ digraph(Conf) when is_list(Conf) -> ?line {'EXIT', {badarg, _}} = (catch family_to_digraph(set([a]))), - ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} = - (catch family_to_digraph(set([a]), [foo])), - ?line {'EXIT', {badarg, [{sofs,family_to_digraph,[_,_],_}|_]}} = - (catch family_to_digraph(F, [foo])), - ?line {'EXIT', {cyclic, [{sofs,family_to_digraph,[_,_],_}|_]}} = - (catch family_to_digraph(family([{a,[a]}]),[acyclic])), + digraph_fail(badarg, catch family_to_digraph(set([a]), [foo])), + digraph_fail(badarg, catch family_to_digraph(F, [foo])), + digraph_fail(cyclic, catch family_to_digraph(family([{a,[a]}]),[acyclic])), ?line G1 = family_to_digraph(E), ?line {'EXIT', {badarg, _}} = (catch digraph_to_family(G1, foo)), @@ -1927,6 +1924,13 @@ digraph(Conf) when is_list(Conf) -> ?line true = T0 == ets:all(), ok. +digraph_fail(ExitReason, Fail) -> + {'EXIT', {ExitReason, [{sofs,family_to_digraph,A,_}|_]}} = Fail, + case {test_server:is_native(sofs),A} of + {false,[_,_]} -> ok; + {true,2} -> ok + end. + constant_function(suite) -> []; constant_function(doc) -> [""]; constant_function(Conf) when is_list(Conf) -> @@ -1952,10 +1956,8 @@ misc(Conf) when is_list(Conf) -> % the "functional" part: ?line eval(union(intersection(partition(1,S), partition(Id,S))), difference(S, RR)), - - %% The function external:foo/1 is undefined. ?line {'EXIT', {undef, _}} = - (catch projection({external,foo}, set([a,b,c]))), + (catch projection(fun external:foo/1, set([a,b,c]))), ok. relational_restriction(R) -> @@ -1968,19 +1970,19 @@ family_specification(doc) -> [""]; family_specification(Conf) when is_list(Conf) -> E = empty_set(), %% internal - ?line eval(family_specification({sofs, is_set}, E), E), + ?line eval(family_specification(fun sofs:is_set/1, E), E), ?line {'EXIT', {badarg, _}} = - (catch family_specification({sofs,is_set}, set([]))), + (catch family_specification(fun sofs:is_set/1, set([]))), ?line F1 = from_term([{1,[1]}]), - ?line eval(family_specification({sofs,is_set}, F1), F1), + ?line eval(family_specification(fun sofs:is_set/1, F1), F1), Fun = fun(S) -> is_subset(S, set([0,1,2,3,4])) end, ?line F2 = family([{a,[1,2]},{b,[3,4,5]}]), ?line eval(family_specification(Fun, F2), family([{a,[1,2]}])), ?line F3 = from_term([{a,[]},{b,[]}]), - ?line eval(family_specification({sofs,is_set}, F3), F3), + ?line eval(family_specification(fun sofs:is_set/1, F3), F3), Fun2 = fun(_) -> throw(fippla) end, ?line fippla = (catch family_specification(Fun2, family([{a,[1]}]))), - Fun3 = fun(_) -> neither_true_or_false end, + Fun3 = fun(_) -> neither_true_nor_false end, ?line {'EXIT', {badarg, _}} = (catch family_specification(Fun3, F3)), @@ -2095,22 +2097,22 @@ family_projection(Conf) when is_list(Conf) -> ?line eval(family_projection(fun(X) -> X end, family([])), E), ?line L1 = [{a,[]}], - ?line eval(family_projection({sofs,union}, E), E), - ?line eval(family_projection({sofs,union}, from_term(L1, SSType)), + ?line eval(family_projection(fun sofs:union/1, E), E), + ?line eval(family_projection(fun sofs:union/1, from_term(L1, SSType)), family(L1)), ?line {'EXIT', {badarg, _}} = - (catch family_projection({sofs,union}, set([]))), + (catch family_projection(fun sofs:union/1, set([]))), ?line {'EXIT', {badarg, _}} = - (catch family_projection({sofs,union}, from_term([{1,[1]}]))), + (catch family_projection(fun sofs:union/1, from_term([{1,[1]}]))), ?line F2 = from_term([{a,[[1],[2]]},{b,[[3,4],[5]]}], SSType), - ?line eval(family_projection({sofs,union}, F2), + ?line eval(family_projection(fun sofs:union/1, F2), family_union(F2)), ?line F3 = from_term([{1,[{a,b},{b,c},{c,d}]},{3,[]},{5,[{3,5}]}], SRType), - ?line eval(family_projection({sofs,domain}, F3), family_domain(F3)), - ?line eval(family_projection({sofs,range}, F3), family_range(F3)), + ?line eval(family_projection(fun sofs:domain/1, F3), family_domain(F3)), + ?line eval(family_projection(fun sofs:range/1, F3), family_range(F3)), ?line eval(family_projection(fun(_) -> E end, family([{a,[b,c]}])), from_term([{a,[]}])), @@ -2290,7 +2292,7 @@ partition_family(Conf) when is_list(Conf) -> ?line eval(partition_family(1, E), E), ?line eval(partition_family(2, E), E), - ?line eval(partition_family({sofs,union}, E), E), + ?line eval(partition_family(fun sofs:union/1, E), E), ?line eval(partition_family(1, ER), EF), ?line eval(partition_family(2, ER), EF), ?line {'EXIT', {badarg, _}} = (catch partition_family(1, set([]))), @@ -2354,7 +2356,7 @@ partition_family(Conf) when is_list(Conf) -> ?line {'EXIT', {badarg, _}} = (catch partition_family({external, fun(X) -> X end}, from_term([[a]]))), - ?line eval(partition_family({sofs,union}, + ?line eval(partition_family(fun sofs:union/1, from_term([[[1],[1,2]], [[1,2]]])), from_term([{[1,2], [[[1],[1,2]],[[1,2]]]}])), ?line eval(partition_family(fun(X) -> X end, diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index fa6faa66f2..71b76c093f 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -34,8 +34,10 @@ %% API tests -export([ sup_start_normal/1, sup_start_ignore_init/1, - sup_start_ignore_child/1, sup_start_error_return/1, - sup_start_fail/1, sup_stop_infinity/1, + sup_start_ignore_child/1, sup_start_ignore_temporary_child/1, + sup_start_ignore_temporary_child_start_child/1, + sup_start_ignore_temporary_child_start_child_simple/1, + sup_start_error_return/1, sup_start_fail/1, sup_stop_infinity/1, sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1, child_adm_simple/1, child_specs/1, extra_return/1]). @@ -85,8 +87,10 @@ all() -> groups() -> [{sup_start, [], [sup_start_normal, sup_start_ignore_init, - sup_start_ignore_child, sup_start_error_return, - sup_start_fail]}, + sup_start_ignore_child, sup_start_ignore_temporary_child, + sup_start_ignore_temporary_child_start_child, + sup_start_ignore_temporary_child_start_child_simple, + sup_start_error_return, sup_start_fail]}, {sup_stop, [], [sup_stop_infinity, sup_stop_timeout, sup_stop_brutal_kill]}, @@ -191,6 +195,59 @@ sup_start_ignore_child(Config) when is_list(Config) -> [2,1,0,2] = get_child_counts(sup_test). %%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when ChildSpec is returned directly from supervisor +%% init callback. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child(Config) when is_list(Config) -> + process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, + 1000, worker, []}, + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child1,Child2]}}), + + [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test), + true = is_pid(CPid2), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when child is started with start_child/2. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child_start_child(Config) when is_list(Config) -> + process_flag(trap_exit, true), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, + 1000, worker, []}, + + {ok, undefined} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), + + [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when child is started with start_child/2, and the +%% supervisor is simple_one_for_one. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child_start_child_simple(Config) + when is_list(Config) -> + process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child1]}}), + + {ok, undefined} = supervisor:start_child(sup_test, []), + {ok, CPid2} = supervisor:start_child(sup_test, []), + + [{undefined, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- %% Tests what happens if init-callback returns a invalid value. sup_start_error_return(Config) when is_list(Config) -> process_flag(trap_exit, true), diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 2f0ecd3863..694d39ce9c 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 1.18 +STDLIB_VSN = 1.18.1 |