aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler')
-rw-r--r--lib/compiler/doc/src/compile.xml26
-rw-r--r--lib/compiler/src/beam_bsm.erl68
-rw-r--r--lib/compiler/src/beam_jump.erl2
-rw-r--r--lib/compiler/src/beam_utils.erl18
-rw-r--r--lib/compiler/src/compile.erl45
-rw-r--r--lib/compiler/src/core_scan.erl27
-rw-r--r--lib/compiler/src/sys_core_fold.erl112
-rw-r--r--lib/compiler/src/sys_pre_expand.erl66
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl30
-rw-r--r--lib/compiler/test/compilation_SUITE.erl3
-rw-r--r--lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl28
-rw-r--r--lib/compiler/test/compile_SUITE.erl30
-rw-r--r--lib/compiler/test/inline_SUITE.erl43
13 files changed, 278 insertions, 220 deletions
diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml
index 27d750f929..ddaae2655d 100644
--- a/lib/compiler/doc/src/compile.xml
+++ b/lib/compiler/doc/src/compile.xml
@@ -816,6 +816,32 @@ pi() -> 3.1416.
</section>
<section>
+ <title>Inlining of list functions</title>
+ <p>The compiler can also inline a variety of list manipulation functions
+ from the stdlib's lists module.</p>
+
+ <p>This feature must be explicitly enabled with a compiler option or a
+ <c>-compile()</c> attribute in the source module.</p>
+
+ <p>To enable inlining of list functions, use the <c>inline_list_funcs</c>
+ option.</p>
+
+ <p>The following functions are inlined:</p>
+ <list type="bulleted">
+ <item><seealso marker="stdlib:lists#all/2">lists:all/2</seealso></item>
+ <item><seealso marker="stdlib:lists#any/2">lists:any/2</seealso></item>
+ <item><seealso marker="stdlib:lists#foreach/2">lists:foreach/2</seealso></item>
+ <item><seealso marker="stdlib:lists#map/2">lists:map/2</seealso></item>
+ <item><seealso marker="stdlib:lists#flatmap/2">lists:flatmap/2</seealso></item>
+ <item><seealso marker="stdlib:lists#filter/2">lists:filter/2</seealso></item>
+ <item><seealso marker="stdlib:lists#foldl/3">lists:foldl/3</seealso></item>
+ <item><seealso marker="stdlib:lists#foldr/3">lists:foldr/3</seealso></item>
+ <item><seealso marker="stdlib:lists#mapfoldl/3">lists:mapfoldl/3</seealso></item>
+ <item><seealso marker="stdlib:lists#mapfoldr/3">lists:mapfoldr/3</seealso></item>
+ </list>
+ </section>
+
+ <section>
<title>Parse Transformations</title>
<p>Parse transformations are used when a programmer wants to use
diff --git a/lib/compiler/src/beam_bsm.erl b/lib/compiler/src/beam_bsm.erl
index 37053e1cc4..02794a8e18 100644
--- a/lib/compiler/src/beam_bsm.erl
+++ b/lib/compiler/src/beam_bsm.erl
@@ -241,21 +241,45 @@ btb_reaches_match_2([{bif,_,{f,F},Ss,Dst}=I|Is], Regs0, D0) ->
Regs = btb_kill([Dst], Regs0),
D = btb_follow_branch(F, Regs, D0),
btb_reaches_match_1(Is, Regs, D);
-btb_reaches_match_2([{test,bs_start_match2,_,_,[Ctx,_],Ctx}|Is], Regs, D) ->
- case btb_context_regs(Regs) of
- [Ctx] ->
- D;
- CtxRegs ->
- case member(Ctx, CtxRegs) of
- false -> btb_reaches_match_2(Is, Regs, D);
- true -> btb_error(unsuitable_bs_start_match)
+btb_reaches_match_2([{test,bs_start_match2,{f,F},Live,[Ctx,_],Ctx}=I|Is],
+ Regs0, D0) ->
+ CtxRegs = btb_context_regs(Regs0),
+ case member(Ctx, CtxRegs) of
+ false ->
+ %% This bs_start_match2 instruction does not use "our"
+ %% match state. Therefore we can continue the search
+ %% for another bs_start_match2 instruction.
+ D = btb_follow_branch(F, Regs0, D0),
+ Regs = btb_kill_not_live(Live, Regs0),
+ btb_reaches_match_2(Is, Regs, D);
+ true ->
+ %% OK. This instruction will use "our" match state,
+ %% but we must make sure that all other copies of the
+ %% match state are killed in the code that follows
+ %% the instruction. (We know that the fail branch cannot
+ %% be taken in this case.)
+ OtherCtxRegs = CtxRegs -- [Ctx],
+ case btb_are_all_unused(OtherCtxRegs, Is, D0) of
+ false -> btb_error({OtherCtxRegs,not_all_unused_after,I});
+ true -> D0
end
end;
-btb_reaches_match_2([{test,bs_start_match2,_,_,[Bin,_],Ctx}|Is], Regs, D) ->
- CtxRegs = btb_context_regs(Regs),
+btb_reaches_match_2([{test,bs_start_match2,{f,F},Live,[Bin,_],Ctx}|Is],
+ Regs0, D0) ->
+ CtxRegs = btb_context_regs(Regs0),
case member(Bin, CtxRegs) orelse member(Ctx, CtxRegs) of
- false -> btb_reaches_match_2(Is, Regs, D);
- true -> btb_error(unsuitable_bs_start_match)
+ false ->
+ %% This bs_start_match2 does not reference any copy of the
+ %% match state. Therefore it can safely be passed on the
+ %% way to another (perhaps more suitable) bs_start_match2
+ %% instruction.
+ D = btb_follow_branch(F, Regs0, D0),
+ Regs = btb_kill_not_live(Live, Regs0),
+ btb_reaches_match_2(Is, Regs, D);
+ true ->
+ %% This variant of the bs_start_match2 instruction does
+ %% not accept a match state as source.
+ btb_error(unsuitable_bs_start_match)
end;
btb_reaches_match_2([{test,_,{f,F},Ss}=I|Is], Regs, D0) ->
btb_ensure_not_used(Ss, I, Regs),
@@ -287,11 +311,11 @@ btb_reaches_match_2([{bs_restore2,Src,_}=I|Is], Regs0, D) ->
btb_reaches_match_1(Is, Regs0, D);
true ->
%% Check that all other copies of the context registers
- %% are killed by the following instructions.
+ %% are unused by the following instructions.
Regs = btb_kill([Src], Regs0),
CtxRegs = btb_context_regs(Regs),
- case btb_are_all_killed(CtxRegs, Is, D) of
- false -> btb_error({CtxRegs,not_all_killed_after,I});
+ case btb_are_all_unused(CtxRegs, Is, D) of
+ false -> btb_error({CtxRegs,not_all_unused_after,I});
true -> D#btb{must_not_save=true}
end
end;
@@ -301,11 +325,11 @@ btb_reaches_match_2([{bs_context_to_binary,Src}=I|Is], Regs0, D) ->
btb_reaches_match_1(Is, Regs0, D);
true ->
%% Check that all other copies of the context registers
- %% are killed by the following instructions.
+ %% are unused by the following instructions.
Regs = btb_kill([Src], Regs0),
CtxRegs = btb_context_regs(Regs),
- case btb_are_all_killed(CtxRegs, Is, D) of
- false -> btb_error({CtxRegs,not_all_killed_after,I});
+ case btb_are_all_unused(CtxRegs, Is, D) of
+ false -> btb_error({CtxRegs,not_all_unused_after,I});
true -> D#btb{must_not_save=true}
end
end;
@@ -343,7 +367,7 @@ btb_call(Arity, Lbl, Regs0, Is, D0) ->
%% tucked away in a y register.
RegList = btb_context_regs(Regs),
YRegs = [R || {y,_}=R <- RegList],
- case btb_are_all_killed(YRegs, Is, D) of
+ case btb_are_all_unused(YRegs, Is, D) of
true -> D;
false -> btb_error({multiple_uses,RegList})
end;
@@ -426,11 +450,11 @@ btb_reaches_match_block([], Regs) ->
Regs.
%% btb_are_all_killed([Register], [Instruction], D) -> true|false
-%% Test whether all of the register are killed in the instruction stream.
+%% Test whether all of the register are unused in the instruction stream.
-btb_are_all_killed(RegList, Is, #btb{index=Li}) ->
+btb_are_all_unused(RegList, Is, #btb{index=Li}) ->
all(fun(R) ->
- beam_utils:is_killed(R, Is, Li)
+ beam_utils:is_not_used(R, Is, Li)
end, RegList).
%% btp_regs_from_list([Register]) -> RegisterSet.
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index b05d01b2a1..636c299e47 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -220,6 +220,8 @@ extract_seq([{line,_}=Line|Is], Acc) ->
extract_seq(Is, [Line|Acc]);
extract_seq([{block,_}=Bl|Is], Acc) ->
extract_seq_1(Is, [Bl|Acc]);
+extract_seq([{bs_context_to_binary,_}=I|Is], Acc) ->
+ extract_seq_1(Is, [I|Acc]);
extract_seq([{label,_}|_]=Is, Acc) ->
extract_seq_1(Is, Acc);
extract_seq(_, _) -> no.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 8b661e6901..8af0447f63 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -263,19 +263,11 @@ check_liveness(R, [{test,_,{f,Fail},As}|Is], St0) ->
{_,_}=Other -> Other
end
end;
-check_liveness(R, [{test,_,{f,Fail},Live,Ss,_}|Is], St0) ->
- case R of
- {x,X} ->
- case X < Live orelse member(R, Ss) of
- true -> {used,St0};
- false -> check_liveness_at(R, Fail, St0)
- end;
- {y,_} ->
- case check_liveness_at(R, Fail, St0) of
- {killed,St} -> check_liveness(R, Is, St);
- {_,_}=Other -> Other
- end
- end;
+check_liveness(R, [{test,Op,Fail,Live,Ss,Dst}|Is], St) ->
+ %% Check this instruction as a block to get a less conservative
+ %% result if the caller is is_not_used/3.
+ Block = [{set,[Dst],Ss,{alloc,Live,{bif,Op,Fail}}}],
+ check_liveness(R, [{block,Block}|Is], St);
check_liveness(R, [{select,_,R,_,_}|_], St) ->
{used,St};
check_liveness(R, [{select,_,_,Fail,Branches}|_], St) ->
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index df1af36eeb..2d1557fa5b 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -248,6 +248,7 @@ format_error({module_name,Mod,Filename}) ->
abstract_code=[], %Abstract code for debugger.
options=[] :: [option()], %Options for compilation
mod_options=[] :: [option()], %Options for module_info
+ encoding=none :: none | epp:source_coding(),
errors=[],
warnings=[]}).
@@ -734,8 +735,9 @@ collect_asm([X | Rest], R) ->
beam_consult_asm(St) ->
case file:consult(St#compile.ifile) of
{ok, Forms0} ->
+ Encoding = epp:read_encoding(St#compile.ifile),
{Module, Forms} = preprocess_asm_forms(Forms0),
- {ok,St#compile{module=Module, code=Forms}};
+ {ok,St#compile{module=Module, code=Forms, encoding=Encoding}};
{error,E} ->
Es = [{St#compile.ifile,[{none,?MODULE,{open,E}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}}
@@ -777,7 +779,8 @@ parse_module(St) ->
R = epp:parse_file(St#compile.ifile, IncludePath, pre_defs(Opts)),
case R of
{ok,Forms} ->
- {ok,St#compile{code=Forms}};
+ Encoding = epp:read_encoding(St#compile.ifile),
+ {ok,St#compile{code=Forms,encoding=Encoding}};
{error,E} ->
Es = [{St#compile.ifile,[{none,?MODULE,{epp,E}}]}],
{error,St#compile{errors=St#compile.errors ++ Es}}
@@ -904,11 +907,8 @@ add_default_base(St, Forms) ->
F = St#compile.filename,
case F of
"" ->
- M = case get_module(Forms) of
- PackageModule when is_list(PackageModule) -> last(PackageModule);
- M0 -> M0
- end,
- St#compile{base = atom_to_list(M)};
+ M = get_module(Forms),
+ St#compile{base=atom_to_list(M)};
_ ->
St
end.
@@ -1339,16 +1339,12 @@ save_binary(#compile{code=none}=St) -> {ok,St};
save_binary(#compile{module=Mod,ofile=Outfile,
options=Opts}=St) ->
%% Test that the module name and output file name match.
- %% We must take care to not completely break a packaged module
- %% (even though packages still is as an experimental, unsupported
- %% feature) - so we will extract the last part of a packaged
- %% module name and compare only that.
case member(no_error_module_mismatch, Opts) of
true ->
save_binary_1(St);
false ->
Base = filename:rootname(filename:basename(Outfile)),
- case lists:last(packages:split(Mod)) of
+ case atom_to_list(Mod) of
Base ->
save_binary_1(St);
_ ->
@@ -1424,28 +1420,28 @@ report_warnings(#compile{options=Opts,warnings=Ws0}) ->
end.
format_message(F, P, [{{Line,Column}=Loc,Mod,E}|Es]) ->
- M = {{F,Loc},io_lib:format("~s:~w:~w ~s~s\n",
+ M = {{F,Loc},io_lib:format("~s:~w:~w ~s~ts\n",
[F,Line,Column,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(F, P, [{Line,Mod,E}|Es]) ->
- M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~s\n",
+ M = {{F,{Line,0}},io_lib:format("~s:~w: ~s~ts\n",
[F,Line,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(F, P, [{Mod,E}|Es]) ->
- M = {none,io_lib:format("~s: ~s~s\n", [F,P,Mod:format_error(E)])},
+ M = {none,io_lib:format("~s: ~s~ts\n", [F,P,Mod:format_error(E)])},
[M|format_message(F, P, Es)];
format_message(_, _, []) -> [].
%% list_errors(File, ErrorDescriptors) -> ok
list_errors(F, [{{Line,Column},Mod,E}|Es]) ->
- io:fwrite("~s:~w:~w: ~s\n", [F,Line,Column,Mod:format_error(E)]),
+ io:fwrite("~s:~w:~w: ~ts\n", [F,Line,Column,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(F, [{Line,Mod,E}|Es]) ->
- io:fwrite("~s:~w: ~s\n", [F,Line,Mod:format_error(E)]),
+ io:fwrite("~s:~w: ~ts\n", [F,Line,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(F, [{Mod,E}|Es]) ->
- io:fwrite("~s: ~s\n", [F,Mod:format_error(E)]),
+ io:fwrite("~s: ~ts\n", [F,Mod:format_error(E)]),
list_errors(F, Es);
list_errors(_F, []) -> ok.
@@ -1501,10 +1497,12 @@ src_listing(Ext, St) ->
Ext, St).
do_src_listing(Lf, Fs) ->
- foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F),"\n"]) end,
+ Opts = [lists:keyfind(encoding, 1, io:getopts(Lf))],
+ foreach(fun (F) -> io:put_chars(Lf, [erl_pp:form(F, Opts),"\n"]) end,
Fs).
-listing(Ext, St) ->
+listing(Ext, St0) ->
+ St = St0#compile{encoding = none},
listing(fun(Lf, Fs) -> beam_listing:module(Lf, Fs) end, Ext, St).
listing(LFun, Ext, St) ->
@@ -1512,6 +1510,7 @@ listing(LFun, Ext, St) ->
case file:open(Lfile, [write,delayed_write]) of
{ok,Lf} ->
Code = restore_expanded_types(Ext, St#compile.code),
+ output_encoding(Lf, St),
LFun(Lf, Code),
ok = file:close(Lf),
{ok,St};
@@ -1520,6 +1519,12 @@ listing(LFun, Ext, St) ->
{error,St#compile{errors=St#compile.errors ++ Es}}
end.
+output_encoding(F, #compile{encoding = none}) ->
+ ok = io:setopts(F, [{encoding, epp:default_encoding()}]);
+output_encoding(F, #compile{encoding = Encoding}) ->
+ ok = io:setopts(F, [{encoding, Encoding}]),
+ ok = io:fwrite(F, <<"%% ~s\n">>, [epp:encoding_to_string(Encoding)]).
+
restore_expanded_types("P", Fs) ->
epp:restore_typed_record_fields(Fs);
restore_expanded_types("E", {M,I,Fs0}) ->
diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl
index 5aab8ae855..0ca2f57dde 100644
--- a/lib/compiler/src/core_scan.erl
+++ b/lib/compiler/src/core_scan.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2000-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
@@ -31,16 +32,16 @@
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%%
%% Many punctuation characters region have special meaning. Must
-%% watch using � \327, bvery close to x \170
+%% watch using × \327, bvery close to x \170
-module(core_scan).
@@ -239,11 +240,11 @@ scan1([C|Cs], Toks, Pos) when C >= $\200, C =< $\240 ->
scan1(Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $a, C =< $z -> %Keywords
scan_key_word(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $ß, C =< $ÿ, C /= $÷ ->
scan_key_word(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $A, C =< $Z -> %Variables
scan_variable(C, Cs, Toks, Pos);
-scan1([C|Cs], Toks, Pos) when C >= $�, C =< $�, C /= $� ->
+scan1([C|Cs], Toks, Pos) when C >= $À, C =< $Þ, C /= $× ->
scan_variable(C, Cs, Toks, Pos);
scan1([C|Cs], Toks, Pos) when C >= $0, C =< $9 -> %Numbers
scan_number(C, Cs, Toks, Pos);
@@ -308,9 +309,9 @@ scan_name([], Ncs) ->
{Ncs,[]}.
name_char(C) when C >= $a, C =< $z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $ß, C =< $ÿ, C /= $÷ -> true;
name_char(C) when C >= $A, C =< $Z -> true;
-name_char(C) when C >= $�, C =< $�, C /= $� -> true;
+name_char(C) when C >= $À, C =< $Þ, C /= $× -> true;
name_char(C) when C >= $0, C =< $9 -> true;
name_char($_) -> true;
name_char($@) -> true;
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index 18fba7962b..f17b0bd130 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -686,11 +686,14 @@ call_1(#c_call{anno=Anno}, lists, all, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=true}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^all',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -713,11 +716,14 @@ call_1(#c_call{anno=Anno}, lists, any, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_case{arg=#c_apply{anno=Anno, op=F, args=[X]},
clauses = [CC1, CC2, CC3]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=false}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^any',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -733,11 +739,14 @@ call_1(#c_call{anno=Anno}, lists, foreach, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_seq{arg=#c_apply{anno=Anno, op=F, args=[X]},
body=#c_apply{anno=Anno, op=Loop, args=[Xs]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=ok}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foreach',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -756,14 +765,18 @@ call_1(#c_call{anno=Anno}, lists, map, [Arg1,Arg2], Sub) ->
op=F,
args=[X]},
body=#c_cons{hd=H,
+ anno=[compiler_generated],
tl=#c_apply{anno=Anno,
op=Loop,
args=[Xs]}}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^map',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -780,18 +793,21 @@ call_1(#c_call{anno=Anno}, lists, flatmap, [Arg1,Arg2], Sub) ->
C1 = #c_clause{pats=[#c_cons{hd=X, tl=Xs}], guard=#c_literal{val=true},
body=#c_let{vars=[H],
arg=#c_apply{anno=Anno, op=F, args=[X]},
- body=#c_call{anno=Anno,
+ body=#c_call{anno=[compiler_generated|Anno],
module=#c_literal{val=erlang},
name=#c_literal{val='++'},
args=[H,
#c_apply{anno=Anno,
op=Loop,
args=[Xs]}]}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^flatmap',1}}|Anno], Err)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -807,7 +823,7 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
B = #c_var{name='B'},
Err1 = #c_tuple{es=[#c_literal{val='case_clause'}, X]},
CC1 = #c_clause{pats=[#c_literal{val=true}], guard=#c_literal{val=true},
- body=#c_cons{hd=X, tl=Xs}},
+ body=#c_cons{anno=[compiler_generated], hd=X, tl=Xs}},
CC2 = #c_clause{pats=[#c_literal{val=false}], guard=#c_literal{val=true},
body=Xs},
CC3 = #c_clause{pats=[X], guard=#c_literal{val=true},
@@ -821,11 +837,14 @@ call_1(#c_call{anno=Anno}, lists, filter, [Arg1,Arg2], Sub) ->
op=Loop,
args=[Xs]},
body=Case}}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=1}]},
body=#c_literal{val=[]}},
- Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err2 = #c_tuple{es=[#c_literal{val='function_clause'}, F, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err2)},
+ body=match_fail([{function_name,{'lists^filter',1}}|Anno], Err2)},
Fun = #c_fun{vars=[Xs],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -845,10 +864,14 @@ call_1(#c_call{anno=Anno}, lists, foldl, [Arg1,Arg2,Arg3], Sub) ->
args=[Xs, #c_apply{anno=Anno,
op=F,
args=[X, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foldl',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -868,10 +891,14 @@ call_1(#c_call{anno=Anno}, lists, foldr, [Arg1,Arg2,Arg3], Sub) ->
args=[X, #c_apply{anno=Anno,
op=Loop,
args=[Xs, A]}]}},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true}, body=A},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
+ body=A},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, A, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^foldr',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, A],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -901,7 +928,10 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
op=Loop,
args=[Xs, Avar]},
#c_tuple{es=[Xs, Avar]},
- #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]})
+ #c_tuple{anno=[compiler_generated],
+ es=[#c_cons{anno=[compiler_generated],
+ hd=X, tl=Xs},
+ Avar]})
%%% Multiple-value version
%%% #c_let{vars=[Xs,A],
%%% %% The tuple here will be optimised
@@ -910,14 +940,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldl, [Arg1,Arg2,Arg3], Sub) ->
%%% body=#c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]}}
)},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
- body=#c_tuple{es=[#c_literal{val=[]}, Avar]}},
+ body=#c_tuple{anno=[compiler_generated],
+ es=[#c_literal{val=[]}, Avar]}},
%%% Multiple-value version
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^mapfoldl',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
@@ -955,7 +989,9 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
#c_tuple{es=[Xs, Avar]},
Match(#c_apply{anno=Anno, op=F, args=[X, Avar]},
#c_tuple{es=[X, Avar]},
- #c_tuple{es=[#c_cons{hd=X, tl=Xs}, Avar]}))
+ #c_tuple{anno=[compiler_generated],
+ es=[#c_cons{anno=[compiler_generated],
+ hd=X, tl=Xs}, Avar]}))
%%% Multiple-value version
%%% body=#c_let{vars=[Xs,A],
%%% %% The tuple will be optimised away
@@ -965,14 +1001,18 @@ call_1(#c_call{anno=Anno}, lists, mapfoldr, [Arg1,Arg2,Arg3], Sub) ->
%%% #c_values{es=[#c_cons{hd=X, tl=Xs},
%%% A]})}
},
- C2 = #c_clause{pats=[#c_literal{val=[]}], guard=#c_literal{val=true},
+ C2 = #c_clause{pats=[#c_literal{val=[]}],
+ guard=#c_call{module=#c_literal{val=erlang},
+ name=#c_literal{val=is_function},
+ args=[F, #c_literal{val=2}]},
%%% Tuple passing version
- body=#c_tuple{es=[#c_literal{val=[]}, Avar]}},
+ body=#c_tuple{anno=[compiler_generated],
+ es=[#c_literal{val=[]}, Avar]}},
%%% Multiple-value version
%%% body=#c_values{es=[#c_literal{val=[]}, A]}},
- Err = #c_tuple{es=[#c_literal{val='function_clause'}, Xs]},
+ Err = #c_tuple{es=[#c_literal{val='function_clause'}, F, Avar, Xs]},
C3 = #c_clause{pats=[Xs], guard=#c_literal{val=true},
- body=match_fail(Anno, Err)},
+ body=match_fail([{function_name,{'lists^mapfoldr',2}}|Anno], Err)},
Fun = #c_fun{vars=[Xs, Avar],
body=#c_case{arg=Xs, clauses=[C1, C2, C3]}},
L = #c_var{name='L'},
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index e55fb2a037..a8c69c3cb1 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -35,10 +35,8 @@
-record(expand, {module=[], %Module name
parameters=undefined, %Module parameters
- package="", %Module package
exports=[], %Exports
imports=[], %Imports
- mod_imports, %Module Imports
compile=[], %Compile flags
attributes=[], %Attributes
callbacks=[], %Callbacks
@@ -67,12 +65,8 @@ module(Fs0, Opts0) ->
%% Set pre-defined exported functions.
PreExp = [{module_info,0},{module_info,1}],
- %% Set pre-defined module imports.
- PreModImp = [{erlang,erlang},{packages,packages}],
-
%% Build initial expand record.
St0 = #expand{exports=PreExp,
- mod_imports=dict:from_list(PreModImp),
compile=Opts,
defined=PreExp,
bitdefault = erl_bits:system_bitdefault(),
@@ -242,14 +236,12 @@ forms([], St) -> {[],St}.
%% Process an attribute, this just affects the state.
attribute(module, {Module, As}, _L, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package=packages:strip_last(M),
+ true = is_atom(Module),
+ St#expand{module=Module,
parameters=As};
attribute(module, Module, _L, St) ->
- M = package_to_string(Module),
- St#expand{module=list_to_atom(M),
- package=packages:strip_last(M)};
+ true = is_atom(Module),
+ St#expand{module=Module};
attribute(export, Es, _L, St) ->
St#expand{exports=union(from_list(Es), St#expand.exports)};
attribute(import, Is, _L, St) ->
@@ -312,8 +304,6 @@ pattern({tuple,Line,Ps}, St0) ->
%%pattern({struct,Line,Tag,Ps}, St0) ->
%% {TPs,TPsvs,St1} = pattern_list(Ps, St0),
%% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1};
-pattern({record_field,_,_,_}=M, St) ->
- {expand_package(M, St),St}; % must be a package name
pattern({bin,Line,Es0}, St0) ->
{Es1,St1} = pattern_bin(Es0, St0),
{{bin,Line,Es1},St1};
@@ -404,8 +394,6 @@ expr({tuple,Line,Es0}, St0) ->
%%expr({struct,Line,Tag,Es0}, Vs, St0) ->
%% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0),
%% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1};
-expr({record_field,_,_,_}=M, St) ->
- {expand_package(M, St),St}; % must be a package name
expr({bin,Line,Es0}, St0) ->
{Es1,St1} = expr_bin(Es0, St0),
{{bin,Line,Es1},St1};
@@ -448,12 +436,9 @@ expr({call,Line,{atom,La,N}=Atom,As0}, St0) ->
end
end
end;
-expr({call,Line,{record_field,_,_,_}=M,As0}, St0) ->
- expr({call,Line,expand_package(M, St0),As0}, St0);
-expr({call,Line,{remote,Lr,M,F},As0}, St0) ->
- M1 = expand_package(M, St0),
- {[M2,F1|As1],St1} = expr_list([M1,F|As0], St0),
- {{call,Line,{remote,Lr,M2,F1},As1},St1};
+expr({call,Line,{remote,Lr,M0,F},As0}, St0) ->
+ {[M1,F1|As1],St1} = expr_list([M0,F|As0], St0),
+ {{call,Line,{remote,Lr,M1,F1},As1},St1};
expr({call,Line,F,As0}, St0) ->
{[Fun1|As1],St1} = expr_list([F|As0], St0),
{{call,Line,Fun1,As1},St1};
@@ -666,32 +651,6 @@ string_to_conses(Line, Cs, Tail) ->
foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs).
-%% In syntax trees, module/package names are atoms or lists of atoms.
-
-package_to_string(A) when is_atom(A) -> atom_to_list(A);
-package_to_string(L) when is_list(L) -> packages:concat(L).
-
-expand_package({atom,L,A} = M, St) ->
- case dict:find(A, St#expand.mod_imports) of
- {ok, A1} ->
- {atom,L,A1};
- error ->
- case packages:is_segmented(A) of
- true ->
- M;
- false ->
- M1 = packages:concat(St#expand.package, A),
- {atom,L,list_to_atom(M1)}
- end
- end;
-expand_package(M, _St) ->
- case erl_parse:package_segments(M) of
- error ->
- M;
- M1 ->
- {atom,element(2,M),list_to_atom(package_to_string(M1))}
- end.
-
%% import(Line, Imports, State) ->
%% State'
%% imported(Name, Arity, State) ->
@@ -699,15 +658,10 @@ expand_package(M, _St) ->
%% Handle import declarations and test for imported functions. No need to
%% check when building imports as code is correct.
-import({Mod0,Fs}, St) ->
- Mod = list_to_atom(package_to_string(Mod0)),
+import({Mod,Fs}, St) ->
+ true = is_atom(Mod),
Mfs = from_list(Fs),
- St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)};
-import(Mod0, St) ->
- Mod = package_to_string(Mod0),
- Key = list_to_atom(packages:last(Mod)),
- St#expand{mod_imports=dict:store(Key, list_to_atom(Mod),
- St#expand.mod_imports)}.
+ St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}.
add_imports(Mod, [F|Fs], Is) ->
add_imports(Mod, Fs, orddict:store(F, Mod, Is));
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index e8f5c55c1a..d63d2235d7 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -33,7 +33,7 @@
matching_meets_construction/1,simon/1,matching_and_andalso/1,
otp_7188/1,otp_7233/1,otp_7240/1,otp_7498/1,
match_string/1,zero_width/1,bad_size/1,haystack/1,
- cover_beam_bool/1,matched_out_size/1]).
+ cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1]).
-export([coverage_id/1,coverage_external_ignore/2]).
@@ -57,7 +57,7 @@ groups() ->
matching_meets_construction,simon,
matching_and_andalso,otp_7188,otp_7233,otp_7240,
otp_7498,match_string,zero_width,bad_size,haystack,
- cover_beam_bool,matched_out_size]}].
+ cover_beam_bool,matched_out_size,follow_fail_branch]}].
init_per_suite(Config) ->
@@ -1108,6 +1108,32 @@ mos_bin(<<L,Bin:L/binary,"abcdefghij">>) ->
L = byte_size(Bin),
Bin.
+follow_fail_branch(_) ->
+ 42 = ffb_1(<<0,1>>, <<0>>),
+ 8 = ffb_1(<<0,1>>, [a]),
+ 42 = ffb_2(<<0,1>>, <<0>>, 17),
+ 8 = ffb_2(<<0,1>>, [a], 0),
+ ok.
+
+ffb_1(<<_,T/bitstring>>, List) ->
+ case List of
+ <<_>> ->
+ 42;
+ [_|_] ->
+ %% The fail branch of the bs_start_match2 instruction
+ %% pointing to here would be ignored, making the compiler
+ %% incorrectly assume that the delayed sub-binary
+ %% optimization was safe.
+ bit_size(T)
+ end.
+
+ffb_2(<<_,T/bitstring>>, List, A) ->
+ case List of
+ <<_>> when A =:= 17 -> 42;
+ [_|_] -> bit_size(T)
+ end.
+
+
check(F, R) ->
R = F().
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index bec97b0199..f8f74e6f7a 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -44,7 +44,7 @@ groups() ->
{group,vsn},otp_2380,otp_2141,otp_2173,otp_4790,
const_list_256,bin_syntax_1,bin_syntax_2,
bin_syntax_3,bin_syntax_4,bin_syntax_5,bin_syntax_6,
- live_var,convopts,bad_functional_value,
+ live_var,convopts,
catch_in_catch,redundant_case,long_string,otp_5076,
complex_guard,otp_5092,otp_5151,otp_5235,otp_5244,
trycatch_4,opt_crash,otp_5404,otp_5436,otp_5481,
@@ -143,7 +143,6 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) ->
?comp(live_var).
?comp(trycatch_4).
-?comp(bad_functional_value).
?comp(catch_in_catch).
diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
deleted file mode 100644
index 126a573e83..0000000000
--- a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl
+++ /dev/null
@@ -1,28 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. 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
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
--module(bad_functional_value).
-
--export([?MODULE/0,a/0]).
-
-?MODULE() ->
- ok.
-
-a() ->
- .list_to_atom("ok").
-
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 2cd75944f4..229e5a98a1 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -27,7 +27,7 @@
app_test/1,
file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
- other_output/1, package_forms/1, encrypted_abstr/1,
+ other_output/1, encrypted_abstr/1,
bad_record_use1/1, bad_record_use2/1, strict_record/1,
missing_testheap/1, cover/1, env/1, core/1, asm/1,
sys_pre_attributes/1]).
@@ -44,7 +44,7 @@ all() ->
test_lib:recompile(?MODULE),
[app_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
- other_output, package_forms, encrypted_abstr,
+ other_output, encrypted_abstr,
{group, bad_record_use}, strict_record,
missing_testheap, cover, env, core, asm,
sys_pre_attributes].
@@ -410,32 +410,6 @@ other_output(Config) when is_list(Config) ->
?line test_server:timetrap_cancel(Dog),
ok.
-package_forms(Config) when is_list(Config) ->
- Fs = [{attribute,1,file,{"./p.erl",1}},
- {attribute,1,module,[p,p]},
- {attribute,3,compile,export_all},
- {attribute,1,file,
- {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}},
- {attribute,6,file,{"./p.erl",6}},
- {function,7,q,0,
- [{clause,7,[],[],
- [{call,8,
- {remote,8,{atom,8,qlc},{atom,8,q}},
- [{tuple,-8,
- [{atom,-8,qlc_lc},
- {'fun',-8,
- {clauses,
- [{clause,-8,[],[],
- [{tuple,-8,
- [{atom,-8,simple_v1},
- {atom,-8,'X'},
- {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}},
- {integer,-8,8}]}]}]}},
- {atom,-8,undefined}]}]}]}]},
- {eof,9}],
- {ok,'p.p',_} = compile:forms(Fs, ['S',report]),
- ok.
-
encrypted_abstr(Config) when is_list(Config) ->
?line Dog = test_server:timetrap(test_server:minutes(10)),
?line {Simple,Target} = files(Config, "encrypted_abstr"),
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index e2eb6a0dec..6dc7548437 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -258,6 +258,49 @@ lists(Config) when is_list(Config) ->
%% Cleanup.
erase(?MODULE),
+
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:map(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:flatmap(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:foreach(fun (X) -> X end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:filter(fun (_) -> true end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:any(fun (_) -> false end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,not_a_list],_}|_]}} =
+ (catch lists:all(fun (_) -> true end, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:foldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:foldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:mapfoldl(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+ {'EXIT',{function_clause,[{?MODULE,_,[_,acc,not_a_list],_}|_]}} =
+ (catch lists:mapfoldr(fun (X, Acc) -> {X,Acc} end, acc, not_a_list)),
+
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:map(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:flatmap(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:foreach(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:filter(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:any(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,[]],_}|_]}} =
+ (catch lists:all(not_a_function, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:foldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:foldr(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:mapfoldl(not_a_function, acc, [])),
+ {'EXIT',{function_clause,[{?MODULE,_,[not_a_function,acc,[]],_}|_]}} =
+ (catch lists:mapfoldr(not_a_function, acc, [])),
+
ok.
my_apply(M, F, A, Init) ->