diff options
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 27 | ||||
-rw-r--r-- | erts/emulator/test/big_SUITE.erl | 15 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_constructed_ber.erl | 2 | ||||
-rw-r--r-- | lib/kernel/src/user_sup.erl | 6 | ||||
-rw-r--r-- | lib/kernel/test/file_SUITE.erl | 4 | ||||
-rw-r--r-- | lib/kernel/test/wrap_log_reader_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_evil_coverage_test.erl | 4 | ||||
-rw-r--r-- | lib/os_mon/src/os_mon_mib.erl | 4 | ||||
-rw-r--r-- | lib/os_mon/test/os_mon_mib_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/otp_mibs/src/otp_mib.erl | 4 | ||||
-rw-r--r-- | lib/parsetools/include/yeccpre.hrl | 5 | ||||
-rw-r--r-- | lib/parsetools/test/yecc_SUITE.erl | 7 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_local_db.erl | 2 | ||||
-rw-r--r-- | lib/stdlib/src/erl_eval.erl | 28 | ||||
-rw-r--r-- | lib/stdlib/src/shell.erl | 7 | ||||
-rw-r--r-- | lib/tools/src/fprof.erl | 12 | ||||
-rw-r--r-- | lib/tools/src/xref_compiler.erl | 7 |
17 files changed, 97 insertions, 41 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 9b2b47ffb7..c65b2be106 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -234,6 +234,12 @@ BeamInstr beam_return_trace[1]; /* OpCode(i_return_trace) */ BeamInstr beam_exception_trace[1]; /* UGLY also OpCode(i_return_trace) */ BeamInstr beam_return_time_trace[1]; /* OpCode(i_return_time_trace) */ + +/* + * We should warn only once for tuple funs. + */ +static erts_smp_atomic_t warned_for_tuple_funs; + /* * All Beam instructions in numerical order. */ @@ -1015,6 +1021,7 @@ init_emulator(void) #if defined(VXWORKS) init_done = 0; #endif + erts_smp_atomic_init_nob(&warned_for_tuple_funs, (erts_aint_t) 0); process_main(); } @@ -6188,6 +6195,26 @@ call_fun(Process* p, /* Current process. */ if (!is_atom(module) || !is_atom(function)) { goto badfun; } + + /* + * If this is the first time a tuple fun is used, + * send a warning to the logger. + */ + if (erts_smp_atomic_xchg_nob(&warned_for_tuple_funs, + (erts_aint_t) 1) == 0) { + erts_dsprintf_buf_t* dsbufp; + + dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf(dsbufp, "Call to tuple fun {%T,%T}.\n\n" + "Tuple funs are deprecated and will be removed " + "in R16. Use \"fun M:F/A\" instead, for example " + "\"fun %T:%T/%d\".\n\n" + "(This warning will only be shown the first time " + "a tuple fun is called.)\n", + module, function, module, function, arity); + erts_send_warning_to_logger(p->group_leader, dsbufp); + } + if ((ep = erts_find_export_entry(module, function, arity)) == NULL) { ep = erts_find_export_entry(erts_proc_get_error_handler(p), am_undefined_function, 3); diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl index 3487917677..413bd3bcae 100644 --- a/erts/emulator/test/big_SUITE.erl +++ b/erts/emulator/test/big_SUITE.erl @@ -26,7 +26,7 @@ shift_limit_1/1, powmod/1, system_limit/1, otp_6692/1]). %% Internal exports. --export([eval/1, funcall/2]). +-export([eval/1]). -export([init/3]). -export([fac/1, fib/1, pow/2, gcd/2, lcm/2]). @@ -162,12 +162,15 @@ multi_match([Node|Ns], Expr, Rs) -> multi_match([], _, Rs) -> Rs. eval(Expr) -> - Fun = {?MODULE,funcall}, - {value,V,_} = erl_eval:expr(Expr, [], Fun), %Applied arithmetic BIFs. - V = eval(Expr, Fun), %Real arithmetic instructions. - V. + LFH = fun(Name, As) -> apply(?MODULE, Name, As) end, + + %% Applied arithmetic BIFs. + {value,V,_} = erl_eval:expr(Expr, [], {value,LFH}), -funcall(F, As) -> apply(?MODULE, F, As). + %% Real arithmetic instructions. + V = eval(Expr, LFH), + + V. %% Like a subset of erl_eval:expr/3, but uses real arithmetic instructions instead of %% applying them (it does make a difference). diff --git a/lib/asn1/src/asn1ct_constructed_ber.erl b/lib/asn1/src/asn1ct_constructed_ber.erl index 77b78dcac7..edeefe1f43 100644 --- a/lib/asn1/src/asn1ct_constructed_ber.erl +++ b/lib/asn1/src/asn1ct_constructed_ber.erl @@ -1542,7 +1542,7 @@ mkfunname(Erule,TopType,Cname,WhatKind,DecOrEnc,Arity) -> F = lists:concat(["fun '",DecOrEnc,"_",EType,"'/",Arity]), {F, "?MODULE", F}; #'Externaltypereference'{module=Mod,type=EType} -> - {lists:concat(["{'",Mod,"','",DecOrEnc,"_",EType,"'}"]),Mod, + {lists:concat(["fun '",Mod,"':'",DecOrEnc,"_",EType,"'/",Arity]),Mod, lists:concat(["'",DecOrEnc,"_",EType,"'"])}; {constructed,bif} -> F = diff --git a/lib/kernel/src/user_sup.erl b/lib/kernel/src/user_sup.erl index 35b7ff0cfe..7c97da189a 100644 --- a/lib/kernel/src/user_sup.erl +++ b/lib/kernel/src/user_sup.erl @@ -45,7 +45,7 @@ init([]) -> Pid = start_slave(Master), {ok, Pid, Pid}; {M, F, A} -> - case start_user({M, F}, A) of + case start_user(M, F, A) of {ok, Pid} -> {ok, Pid, Pid}; Error -> @@ -95,8 +95,8 @@ terminate(_Reason, UserPid) -> %% is guaranteed that the user is started. %%----------------------------------------------------------------- -start_user(Func,A) -> - apply(Func, A), +start_user(Mod, Func, A) -> + apply(Mod, Func, A), wait_for_user_p(100). wait_for_user_p(0) -> diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 77fc7e73f9..85346762ac 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -3144,12 +3144,12 @@ ipread_int(Dir, ModeList) -> {fun (Bin) when is_binary(Bin) -> Bin; (List) when is_list(List) -> list_to_binary(List) end, - {erlang, size}}; + fun erlang:byte_size/1}; false -> {fun (Bin) when is_binary(Bin) -> binary_to_list(Bin); (List) when is_list(List) -> List end, - {erlang, length}} + fun erlang:length/1} end, ?line Pos = 4711, ?line Data = Conv("THE QUICK BROWN FOX JUMPS OVER A LAZY DOG"), diff --git a/lib/kernel/test/wrap_log_reader_SUITE.erl b/lib/kernel/test/wrap_log_reader_SUITE.erl index ffc8def626..96dc3e6d33 100644 --- a/lib/kernel/test/wrap_log_reader_SUITE.erl +++ b/lib/kernel/test/wrap_log_reader_SUITE.erl @@ -561,4 +561,4 @@ rec(M, Where) -> end. pps() -> - {erlang:ports(), lists:filter({erlang, is_process_alive}, processes())}. + {erlang:ports(), lists:filter(fun erlang:is_process_alive/1, processes())}. diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl index 17d6c6c212..c1918071a1 100644 --- a/lib/mnesia/test/mnesia_evil_coverage_test.erl +++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl @@ -244,7 +244,7 @@ db_node_lifecycle(Config) when is_list(Config) -> ?match([], mnesia_test_lib:start_mnesia(AllNodes)), ?match([SNs, SNs, SNs], - lists:map({lists, sort}, + lists:map(fun lists:sort/1, element(1, rpc:multicall(AllNodes, mnesia, table_info, [schema, disc_copies])))), @@ -259,7 +259,7 @@ db_node_lifecycle(Config) when is_list(Config) -> mnesia:change_table_copy_type(schema, Node2, disc_copies)), ?match([SNs, SNs, SNs], - lists:map({lists, sort}, + lists:map(fun lists:sort/1, element(1, rpc:multicall(AllNodes, mnesia, table_info, [schema, disc_copies])))), diff --git a/lib/os_mon/src/os_mon_mib.erl b/lib/os_mon/src/os_mon_mib.erl index a4ce274a16..c972913b03 100644 --- a/lib/os_mon/src/os_mon_mib.erl +++ b/lib/os_mon/src/os_mon_mib.erl @@ -65,11 +65,11 @@ %% Shadow argument macros -define(loadShadowArgs, {loadTable, string, record_info(fields, loadTable), 5000, - {os_mon_mib, update_load_table}}). + fun os_mon_mib:update_load_table/0}). -define(diskShadowArgs, {diskTable, {integer, integer}, record_info(fields, diskTable), 5000, - {os_mon_mib, update_disk_table}}). + fun os_mon_mib:update_disk_table/0}). %% Misc -record(diskAlloc, {diskDescr, diskId}). diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl index 4bd256a3f7..a137efc441 100644 --- a/lib/os_mon/test/os_mon_mib_SUITE.erl +++ b/lib/os_mon/test/os_mon_mib_SUITE.erl @@ -718,7 +718,7 @@ del_dir(Dir) -> {ok, Files} = file:list_dir(Dir), FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end, Files), - lists:foreach({file, delete}, FullPathFiles), + lists:foreach(fun file:delete/1, FullPathFiles), file:del_dir(Dir). %%--------------------------------------------------------------------- diff --git a/lib/otp_mibs/src/otp_mib.erl b/lib/otp_mibs/src/otp_mib.erl index e8b0e51b91..1b0211df02 100644 --- a/lib/otp_mibs/src/otp_mib.erl +++ b/lib/otp_mibs/src/otp_mib.erl @@ -48,11 +48,11 @@ %% Shadow argument macros -define(erlNodeShadowArgs, {erlNodeTable, integer, record_info(fields, erlNodeTable), 5000, - {otp_mib, update_erl_node_table}}). + fun otp_mib:update_erl_node_table/0}). -define(applShadowArgs, {applTable, {integer, integer}, record_info(fields, applTable), - 5000, {otp_mib, update_appl_table}}). + 5000, fun otp_mib:update_appl_table/0}). %% Misc -record(erlNodeAlloc, {nodeName, nodeId}). diff --git a/lib/parsetools/include/yeccpre.hrl b/lib/parsetools/include/yeccpre.hrl index f638529aa4..3672394fc5 100644 --- a/lib/parsetools/include/yeccpre.hrl +++ b/lib/parsetools/include/yeccpre.hrl @@ -28,10 +28,11 @@ parse(Tokens) -> -spec parse_and_scan({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) -> yecc_ret(). -parse_and_scan({F, A}) -> % Fun or {M, F} +parse_and_scan({F, A}) -> yeccpars0([], {{F, A}, no_line}, 0, [], []); parse_and_scan({M, F, A}) -> - yeccpars0([], {{{M, F}, A}, no_line}, 0, [], []). + Arity = length(A), + yeccpars0([], {{fun M:F/Arity, A}, no_line}, 0, [], []). -spec format_error(any()) -> [char() | list()]. format_error(Message) -> diff --git a/lib/parsetools/test/yecc_SUITE.erl b/lib/parsetools/test/yecc_SUITE.erl index a5f66b48e9..3d26adf1be 100644 --- a/lib/parsetools/test/yecc_SUITE.erl +++ b/lib/parsetools/test/yecc_SUITE.erl @@ -1197,7 +1197,7 @@ yeccpre(Config) when is_list(Config) -> catch error: error -> ok end, - try parse_and_scan({{yecc_test, scan}, [exit]}) + try parse_and_scan({fun yecc_test:scan/1, [exit]}) catch exit: exit -> ok end, @@ -1650,10 +1650,11 @@ yeccpre_v1_2() -> parse(Tokens) -> yeccpars0(Tokens, false). -parse_and_scan({F, A}) -> % Fun or {M, F} +parse_and_scan({F, A}) -> yeccpars0([], {F, A}); parse_and_scan({M, F, A}) -> - yeccpars0([], {{M, F}, A}). + Arity = length(A), + yeccpars0([], {fun M:F/Arity, A}). format_error(Message) -> case io_lib:deep_char_list(Message) of diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index d9d6e633de..df01091d53 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -1110,7 +1110,7 @@ table_func(is_set_ok, RowIndex, Cols, NameDb) -> table_func(set, RowIndex, Cols, NameDb) -> snmp_generic:table_set_row(NameDb, nofunc, - {snmp_generic, table_try_make_consistent}, + fun snmp_generic:table_try_make_consistent/3, RowIndex, Cols); diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 88a0094d57..bf3c7b3504 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -341,7 +341,7 @@ expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs) -> true -> bif(F, As, Bs3, Ef, RBs); false -> - do_apply({M,F}, As, Bs3, Ef, RBs) + do_apply(M, F, As, Bs3, Ef, RBs) end; expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs) -> case erl_internal:bif(Func, length(As0)) of @@ -499,11 +499,11 @@ local_func2({eval,F,As,Bs}, RBs) -> % This reply is not documented. bif(apply, [erlang,apply,As], Bs, Ef, RBs) -> bif(apply, As, Bs, Ef, RBs); bif(apply, [M,F,As], Bs, Ef, RBs) -> - do_apply({M,F}, As, Bs, Ef, RBs); + do_apply(M, F, As, Bs, Ef, RBs); bif(apply, [F,As], Bs, Ef, RBs) -> do_apply(F, As, Bs, Ef, RBs); bif(Name, As, Bs, Ef, RBs) -> - do_apply({erlang,Name}, As, Bs, Ef, RBs). + do_apply(erlang, Name, As, Bs, Ef, RBs). %% do_apply(MF, Arguments, Bindings, ExternalFuncHandler, RBs) -> %% {value,Value,Bindings} | Value when @@ -563,6 +563,19 @@ do_apply(Func, As, Bs0, Ef, RBs) -> ret_expr(F(Func, As), Bs0, RBs) end. +do_apply(Mod, Func, As, Bs0, Ef, RBs) -> + case Ef of + none when RBs =:= value -> + %% Make tail recursive calls when possible. + apply(Mod, Func, As); + none -> + ret_expr(apply(Mod, Func, As), Bs0, RBs); + {value,F} when RBs =:= value -> + F({Mod,Func}, As); + {value,F} -> + ret_expr(F({Mod,Func}, As), Bs0, RBs) + end. + %% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler, %% ExternalFuncHandler, RetBindings) -> %% {value,Value,Bindings} | Value @@ -731,10 +744,10 @@ expr_list([], Vs, _, Bs, _Lf, _Ef) -> {reverse(Vs),Bs}. eval_op(Op, Arg1, Arg2, Bs, Ef, RBs) -> - do_apply({erlang,Op}, [Arg1,Arg2], Bs, Ef, RBs). + do_apply(erlang, Op, [Arg1,Arg2], Bs, Ef, RBs). eval_op(Op, Arg, Bs, Ef, RBs) -> - do_apply({erlang,Op}, [Arg], Bs, Ef, RBs). + do_apply(erlang, Op, [Arg], Bs, Ef, RBs). %% if_clauses(Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, RBs) @@ -920,8 +933,9 @@ guard0([], _Bs, _Lf, _Ef) -> true. guard_test({call,L,{atom,Ln,F},As0}, Bs0, Lf, Ef) -> TT = type_test(F), - guard_test({call,L,{tuple,Ln,[{atom,Ln,erlang},{atom,Ln,TT}]},As0}, - Bs0, Lf, Ef); + G = {call,L,{atom,Ln,TT},As0}, + try {value,true,_} = expr(G, Bs0, Lf, Ef, none) + catch error:_ -> {value,false,Bs0} end; guard_test({call,L,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,_F}=T},As0}, Bs0, Lf, Ef) -> guard_test({call,L,T,As0}, Bs0, Lf, Ef); diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index 964697cae6..dc450f0ee6 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -1065,9 +1065,10 @@ local_func(F, As0, Bs0, _Shell, _RT, Lf, Ef) when is_atom(F) -> non_builtin_local_func(F,As,Bs). non_builtin_local_func(F,As,Bs) -> - case erlang:function_exported(user_default, F, length(As)) of + Arity = length(As), + case erlang:function_exported(user_default, F, Arity) of true -> - {eval,{user_default,F},As,Bs}; + {eval,erlang:make_fun(user_default, F, Arity),As,Bs}; false -> shell_default(F,As,Bs) end. @@ -1079,7 +1080,7 @@ shell_default(F,As,Bs) -> {module, _} -> case erlang:function_exported(M,F,A) of true -> - {eval,{M,F},As,Bs}; + {eval,erlang:make_fun(M, F, A),As,Bs}; false -> shell_undef(F,A) end; diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 155965a65a..1d85a55bd7 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -87,8 +87,10 @@ dbg(_, _, _) -> -apply({M, F} = Function, Args) +apply({M, F}, Args) when is_atom(M), is_atom(F), is_list(Args) -> + Arity = length(Args), + Function = fun M:F/Arity, apply_1(Function, Args, []); apply(Fun, Args) when is_function(Fun), is_list(Args) -> @@ -98,8 +100,10 @@ apply(A, B) -> apply(M, F, Args) when is_atom(M), is_atom(F), is_list(Args) -> apply_1({M, F}, Args, []); -apply({M, F} = Function, Args, Options) +apply({M, F}, Args, Options) when is_atom(M), is_atom(F), is_list(Args), is_list(Options) -> + Arity = length(Args), + Function = fun M:F/Arity, apply_1(Function, Args, Options); apply(Fun, Args, Options) when is_function(Fun), is_list(Args), is_list(Options) -> @@ -109,7 +113,9 @@ apply(A, B, C) -> apply(Module, Function, Args, Options) when is_atom(Module), is_atom(Function), is_list(Args), is_list(Options) -> - apply_1({Module, Function}, Args, Options); + Arity = length(Args), + Fun = fun Module:Function/Arity, + apply_1(Fun, Args, Options); apply(A, B, C, D) -> erlang:error(badarg, [A, B, C, D]). diff --git a/lib/tools/src/xref_compiler.erl b/lib/tools/src/xref_compiler.erl index 1445e135be..e6f492c62b 100644 --- a/lib/tools/src/xref_compiler.erl +++ b/lib/tools/src/xref_compiler.erl @@ -736,8 +736,11 @@ find_nodes(Tuple, I, T) when is_tuple(Tuple) -> end, {NL, NI, T1} = foldl(Fun, {[], I, T}, L), Tag = case Tag0 of - _ when is_function(Tag0) -> Tag0; - _ when is_atom(Tag0) -> {sofs, Tag0} + _ when is_function(Tag0) -> + Tag0; + _ when is_atom(Tag0) -> + Arity = length(NL), + fun sofs:Tag0/Arity end, find_node({apply, Tag, NL}, NI, T1). |