aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstrap/lib/compiler/ebin/beam_asm.beambin11096 -> 11640 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_block.beambin14388 -> 14388 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bool.beambin16160 -> 16160 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_bsm.beambin13728 -> 13728 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_clean.beambin11468 -> 11468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dead.beambin11880 -> 11880 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_dict.beambin5360 -> 5364 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_disasm.beambin24968 -> 24968 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_jump.beambin9516 -> 9516 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_listing.beambin2904 -> 2904 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_receive.beambin5832 -> 5832 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_trim.beambin8568 -> 8568 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_type.beambin13820 -> 13820 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_utils.beambin14532 -> 14532 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/beam_validator.beambin34328 -> 34328 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_inline.beambin37300 -> 37300 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/cerl_trees.beambin18960 -> 18960 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/compile.beambin36920 -> 36920 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lib.beambin5468 -> 5468 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_lint.beambin11632 -> 11632 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/core_pp.beambin12124 -> 12124 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/rec_env.beambin4780 -> 4780 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_dsetel.beambin6996 -> 6996 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_fold.beambin47520 -> 47520 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_core_inline.beambin4212 -> 4212 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/sys_pre_expand.beambin16504 -> 16188 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_codegen.beambin53752 -> 53752 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_core.beambin50836 -> 50988 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel.beambin44748 -> 44604 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_kernel_pp.beambin11828 -> 11828 bytes
-rw-r--r--bootstrap/lib/compiler/ebin/v3_life.beambin23528 -> 23528 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application.beambin2940 -> 3772 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_controller.beambin30684 -> 30684 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/application_master.beambin6352 -> 6352 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code.beambin6732 -> 6732 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/code_server.beambin25956 -> 25956 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log.beambin36248 -> 36444 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/disk_log_server.beambin6408 -> 6408 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/dist_ac.beambin26708 -> 26708 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/erts_debug.beambin2808 -> 2808 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_io_server.beambin14196 -> 14196 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/file_server.beambin5124 -> 5124 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global.beambin32236 -> 32236 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/global_group.beambin17728 -> 17728 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/group.beambin11776 -> 11776 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/hipe_unified_loader.beambin12540 -> 12540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet.beambin19688 -> 19688 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet6_tcp_dist.beambin6256 -> 6256 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_config.beambin8192 -> 8192 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_db.beambin26424 -> 26424 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_gethost_native.beambin10500 -> 10500 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_parse.beambin13056 -> 13056 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_res.beambin14816 -> 14816 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/inet_tcp_dist.beambin6540 -> 6540 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/kernel_config.beambin2720 -> 2720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/net_kernel.beambin22720 -> 22720 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/os.beambin5228 -> 5228 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/packages.beambin2244 -> 2244 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/pg2.beambin7696 -> 7696 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/rpc.beambin8748 -> 8748 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/standard_error.beambin3636 -> 3636 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user.beambin12360 -> 12360 bytes
-rw-r--r--bootstrap/lib/kernel/ebin/user_drv.beambin10084 -> 10308 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/array.beambin12036 -> 12036 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/beam_lib.beambin18220 -> 18220 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/c.beambin13932 -> 13932 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets.beambin53204 -> 53468 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_server.beambin7020 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_utils.beambin28864 -> 28864 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v8.beambin27508 -> 27520 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dets_v9.beambin50272 -> 50104 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/dict.beambin9140 -> 9140 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph.beambin8320 -> 8320 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/digraph_utils.beambin6800 -> 6800 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin24216 -> 24188 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_compile.beambin5076 -> 5076 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_eval.beambin23480 -> 23552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_expand_records.beambin21812 -> 21812 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_lint.beambin84792 -> 84904 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_parse.beambin71068 -> 71496 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_pp.beambin23228 -> 23344 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_scan.beambin31776 -> 31776 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/erl_tar.beambin15352 -> 15352 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/escript.beambin17044 -> 17044 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ets.beambin20048 -> 20048 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/file_sorter.beambin30608 -> 30608 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_event.beambin12900 -> 17412 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_fsm.beambin9412 -> 14764 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/gen_server.beambin12508 -> 16780 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/io_lib_pretty.beambin12372 -> 12372 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lib.beambin9072 -> 9072 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin29204 -> 29204 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/log_mf_h.beambin2644 -> 2644 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/ms_transform.beambin20316 -> 20224 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/orddict.beambin2748 -> 2748 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/pool.beambin3848 -> 3848 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/proc_lib.beambin9200 -> 9200 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc.beambin69344 -> 69376 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/qlc_pt.beambin71592 -> 71592 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/random.beambin1580 -> 1576 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/re.beambin12376 -> 12376 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sets.beambin7020 -> 7020 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/shell.beambin30568 -> 30568 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sofs.beambin41096 -> 41096 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor.beambin18136 -> 21220 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/supervisor_bridge.beambin1980 -> 2760 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/sys.beambin7328 -> 7328 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/timer.beambin5452 -> 5452 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/unicode.beambin11552 -> 11552 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/zip.beambin26824 -> 26824 bytes
-rw-r--r--erts/doc/src/absform.xml3
-rw-r--r--erts/doc/src/erlang.xml9
-rw-r--r--erts/emulator/beam/beam_bif_load.c2
-rw-r--r--erts/emulator/beam/beam_load.c8
-rw-r--r--erts/emulator/test/code_SUITE.erl31
-rw-r--r--erts/emulator/test/code_SUITE_data/fun_confusion.erl31
-rw-r--r--lib/compiler/src/beam_asm.erl52
-rw-r--r--lib/compiler/src/beam_dict.erl15
-rw-r--r--lib/compiler/src/sys_pre_expand.erl35
-rw-r--r--lib/compiler/src/v3_core.erl7
-rw-r--r--lib/compiler/src/v3_kernel.erl22
-rw-r--r--lib/compiler/test/fun_SUITE.erl52
-rw-r--r--lib/compiler/test/pmod_SUITE.erl4
-rw-r--r--lib/debugger/src/dbg_ieval.erl15
-rw-r--r--lib/debugger/src/dbg_iload.erl8
-rw-r--r--lib/debugger/test/fun_SUITE.erl52
-rw-r--r--lib/ssl/src/ssl_cipher.erl80
-rw-r--r--lib/ssl/test/Makefile2
-rw-r--r--lib/ssl/test/ssl_cipher_SUITE.erl163
-rw-r--r--lib/stdlib/examples/erl_id_trans.erl9
-rw-r--r--lib/stdlib/src/erl_eval.erl3
-rw-r--r--lib/stdlib/src/erl_lint.erl9
-rw-r--r--lib/stdlib/src/erl_parse.yrl12
-rw-r--r--lib/stdlib/src/erl_pp.erl10
-rw-r--r--lib/stdlib/src/qlc.erl5
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl6
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl5
-rw-r--r--lib/stdlib/test/qlc_SUITE.erl2
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl7
-rw-r--r--lib/tools/src/xref_reader.erl25
-rw-r--r--lib/tools/test/cover_SUITE.erl31
-rw-r--r--lib/tools/test/cover_SUITE_data/otp_6115/f1.erl11
-rw-r--r--lib/tools/test/xref_SUITE.erl87
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.beambin0 -> 1116 bytes
-rw-r--r--lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl18
-rw-r--r--system/doc/reference_manual/code_loading.xml4
-rw-r--r--system/doc/reference_manual/expressions.xml10
147 files changed, 698 insertions, 147 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam
index c14ccc2e7b..103ed82529 100644
--- a/bootstrap/lib/compiler/ebin/beam_asm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_asm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_block.beam b/bootstrap/lib/compiler/ebin/beam_block.beam
index 8983932f86..a5699221fe 100644
--- a/bootstrap/lib/compiler/ebin/beam_block.beam
+++ b/bootstrap/lib/compiler/ebin/beam_block.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bool.beam b/bootstrap/lib/compiler/ebin/beam_bool.beam
index e540fe227b..d8f91ec36d 100644
--- a/bootstrap/lib/compiler/ebin/beam_bool.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bool.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_bsm.beam b/bootstrap/lib/compiler/ebin/beam_bsm.beam
index bde0cff4cb..02f82a9341 100644
--- a/bootstrap/lib/compiler/ebin/beam_bsm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_bsm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_clean.beam b/bootstrap/lib/compiler/ebin/beam_clean.beam
index b902d84ffa..70523ca134 100644
--- a/bootstrap/lib/compiler/ebin/beam_clean.beam
+++ b/bootstrap/lib/compiler/ebin/beam_clean.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dead.beam b/bootstrap/lib/compiler/ebin/beam_dead.beam
index 449ce06f60..b177adb455 100644
--- a/bootstrap/lib/compiler/ebin/beam_dead.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dead.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_dict.beam b/bootstrap/lib/compiler/ebin/beam_dict.beam
index 2811a0e705..81e62b0a7d 100644
--- a/bootstrap/lib/compiler/ebin/beam_dict.beam
+++ b/bootstrap/lib/compiler/ebin/beam_dict.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam
index 0d4f028d48..377c738709 100644
--- a/bootstrap/lib/compiler/ebin/beam_disasm.beam
+++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_jump.beam b/bootstrap/lib/compiler/ebin/beam_jump.beam
index ea93fca2a0..f45b8d3124 100644
--- a/bootstrap/lib/compiler/ebin/beam_jump.beam
+++ b/bootstrap/lib/compiler/ebin/beam_jump.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_listing.beam b/bootstrap/lib/compiler/ebin/beam_listing.beam
index f0503e4674..662edc0651 100644
--- a/bootstrap/lib/compiler/ebin/beam_listing.beam
+++ b/bootstrap/lib/compiler/ebin/beam_listing.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_receive.beam b/bootstrap/lib/compiler/ebin/beam_receive.beam
index 0836e118c9..ae873a1082 100644
--- a/bootstrap/lib/compiler/ebin/beam_receive.beam
+++ b/bootstrap/lib/compiler/ebin/beam_receive.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_trim.beam b/bootstrap/lib/compiler/ebin/beam_trim.beam
index 04d3416ef2..b1275f787a 100644
--- a/bootstrap/lib/compiler/ebin/beam_trim.beam
+++ b/bootstrap/lib/compiler/ebin/beam_trim.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_type.beam b/bootstrap/lib/compiler/ebin/beam_type.beam
index e0a09eb146..67e6dbd8a1 100644
--- a/bootstrap/lib/compiler/ebin/beam_type.beam
+++ b/bootstrap/lib/compiler/ebin/beam_type.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam
index a8bb6ec1a2..b80810bfb2 100644
--- a/bootstrap/lib/compiler/ebin/beam_utils.beam
+++ b/bootstrap/lib/compiler/ebin/beam_utils.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/beam_validator.beam b/bootstrap/lib/compiler/ebin/beam_validator.beam
index 02226a600a..211c56424e 100644
--- a/bootstrap/lib/compiler/ebin/beam_validator.beam
+++ b/bootstrap/lib/compiler/ebin/beam_validator.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_inline.beam b/bootstrap/lib/compiler/ebin/cerl_inline.beam
index e6f76ad0d4..582604e3cc 100644
--- a/bootstrap/lib/compiler/ebin/cerl_inline.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/cerl_trees.beam b/bootstrap/lib/compiler/ebin/cerl_trees.beam
index b2d79c924c..673954eaac 100644
--- a/bootstrap/lib/compiler/ebin/cerl_trees.beam
+++ b/bootstrap/lib/compiler/ebin/cerl_trees.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam
index 4985e3d6da..bead5a1399 100644
--- a/bootstrap/lib/compiler/ebin/compile.beam
+++ b/bootstrap/lib/compiler/ebin/compile.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lib.beam b/bootstrap/lib/compiler/ebin/core_lib.beam
index 2421df60bd..ddb5278d00 100644
--- a/bootstrap/lib/compiler/ebin/core_lib.beam
+++ b/bootstrap/lib/compiler/ebin/core_lib.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_lint.beam b/bootstrap/lib/compiler/ebin/core_lint.beam
index de6f3e5c25..225fa95aea 100644
--- a/bootstrap/lib/compiler/ebin/core_lint.beam
+++ b/bootstrap/lib/compiler/ebin/core_lint.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam
index 9d812001b8..f1841d810b 100644
--- a/bootstrap/lib/compiler/ebin/core_pp.beam
+++ b/bootstrap/lib/compiler/ebin/core_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/rec_env.beam b/bootstrap/lib/compiler/ebin/rec_env.beam
index c04176da61..91a86d9855 100644
--- a/bootstrap/lib/compiler/ebin/rec_env.beam
+++ b/bootstrap/lib/compiler/ebin/rec_env.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
index 4a44c53aed..0764734cb1 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_dsetel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
index 2ed16cc07a..b07afc0938 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_core_inline.beam b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
index 3d6f3103e0..5b9e9d7c3e 100644
--- a/bootstrap/lib/compiler/ebin/sys_core_inline.beam
+++ b/bootstrap/lib/compiler/ebin/sys_core_inline.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
index 9d1629d9d4..12664c7270 100644
--- a/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
+++ b/bootstrap/lib/compiler/ebin/sys_pre_expand.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam
index dbc5fb5e3a..3a8d68a611 100644
--- a/bootstrap/lib/compiler/ebin/v3_codegen.beam
+++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam
index 817938781d..ff7144c2bc 100644
--- a/bootstrap/lib/compiler/ebin/v3_core.beam
+++ b/bootstrap/lib/compiler/ebin/v3_core.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam
index a52d44b32e..48b89b374b 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
index 4bec626689..485aa63dcb 100644
--- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
+++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam
Binary files differ
diff --git a/bootstrap/lib/compiler/ebin/v3_life.beam b/bootstrap/lib/compiler/ebin/v3_life.beam
index d3ffc45a26..b7996884f4 100644
--- a/bootstrap/lib/compiler/ebin/v3_life.beam
+++ b/bootstrap/lib/compiler/ebin/v3_life.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application.beam b/bootstrap/lib/kernel/ebin/application.beam
index be05505c35..5bdfcefb87 100644
--- a/bootstrap/lib/kernel/ebin/application.beam
+++ b/bootstrap/lib/kernel/ebin/application.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_controller.beam b/bootstrap/lib/kernel/ebin/application_controller.beam
index 996836d78e..565691df01 100644
--- a/bootstrap/lib/kernel/ebin/application_controller.beam
+++ b/bootstrap/lib/kernel/ebin/application_controller.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/application_master.beam b/bootstrap/lib/kernel/ebin/application_master.beam
index 98bd12a42f..4d1098bcec 100644
--- a/bootstrap/lib/kernel/ebin/application_master.beam
+++ b/bootstrap/lib/kernel/ebin/application_master.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam
index 580dc1f888..3d2bf91b93 100644
--- a/bootstrap/lib/kernel/ebin/code.beam
+++ b/bootstrap/lib/kernel/ebin/code.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam
index 9ed647a94b..f0be53008b 100644
--- a/bootstrap/lib/kernel/ebin/code_server.beam
+++ b/bootstrap/lib/kernel/ebin/code_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam
index 15953c9931..cd01c579bf 100644
--- a/bootstrap/lib/kernel/ebin/disk_log.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/disk_log_server.beam b/bootstrap/lib/kernel/ebin/disk_log_server.beam
index 96c17f1586..39197f3995 100644
--- a/bootstrap/lib/kernel/ebin/disk_log_server.beam
+++ b/bootstrap/lib/kernel/ebin/disk_log_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/dist_ac.beam b/bootstrap/lib/kernel/ebin/dist_ac.beam
index d20390087d..c86598a689 100644
--- a/bootstrap/lib/kernel/ebin/dist_ac.beam
+++ b/bootstrap/lib/kernel/ebin/dist_ac.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam
index b812127f18..b7bf2ea58e 100644
--- a/bootstrap/lib/kernel/ebin/erts_debug.beam
+++ b/bootstrap/lib/kernel/ebin/erts_debug.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_io_server.beam b/bootstrap/lib/kernel/ebin/file_io_server.beam
index b35b96d8f0..3783cd7b11 100644
--- a/bootstrap/lib/kernel/ebin/file_io_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_io_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/file_server.beam b/bootstrap/lib/kernel/ebin/file_server.beam
index 71e2ad8c0d..7b03c3ea0d 100644
--- a/bootstrap/lib/kernel/ebin/file_server.beam
+++ b/bootstrap/lib/kernel/ebin/file_server.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global.beam b/bootstrap/lib/kernel/ebin/global.beam
index a9e0e2c0d1..8049d8d729 100644
--- a/bootstrap/lib/kernel/ebin/global.beam
+++ b/bootstrap/lib/kernel/ebin/global.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/global_group.beam b/bootstrap/lib/kernel/ebin/global_group.beam
index c6fe47b456..f1e6fa219e 100644
--- a/bootstrap/lib/kernel/ebin/global_group.beam
+++ b/bootstrap/lib/kernel/ebin/global_group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam
index b8d55c4e29..67f78948d4 100644
--- a/bootstrap/lib/kernel/ebin/group.beam
+++ b/bootstrap/lib/kernel/ebin/group.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
index b638157e11..c4a1a850a7 100644
--- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
+++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet.beam b/bootstrap/lib/kernel/ebin/inet.beam
index 0c4607063d..5a483c6265 100644
--- a/bootstrap/lib/kernel/ebin/inet.beam
+++ b/bootstrap/lib/kernel/ebin/inet.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
index 145e039f7e..1bc785fa37 100644
--- a/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet6_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam
index d937ef4a7b..fc1e2c8387 100644
--- a/bootstrap/lib/kernel/ebin/inet_config.beam
+++ b/bootstrap/lib/kernel/ebin/inet_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_db.beam b/bootstrap/lib/kernel/ebin/inet_db.beam
index ee3fbaa584..d2c636d21f 100644
--- a/bootstrap/lib/kernel/ebin/inet_db.beam
+++ b/bootstrap/lib/kernel/ebin/inet_db.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
index c53ecfb42a..4bf616ad46 100644
--- a/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
+++ b/bootstrap/lib/kernel/ebin/inet_gethost_native.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam
index f8d3102da7..14ca272933 100644
--- a/bootstrap/lib/kernel/ebin/inet_parse.beam
+++ b/bootstrap/lib/kernel/ebin/inet_parse.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam
index c0f00a0c12..9e8e9fa4de 100644
--- a/bootstrap/lib/kernel/ebin/inet_res.beam
+++ b/bootstrap/lib/kernel/ebin/inet_res.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
index b382eebf92..22f2db4182 100644
--- a/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
+++ b/bootstrap/lib/kernel/ebin/inet_tcp_dist.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/kernel_config.beam b/bootstrap/lib/kernel/ebin/kernel_config.beam
index 40228eeeee..c5a63b6217 100644
--- a/bootstrap/lib/kernel/ebin/kernel_config.beam
+++ b/bootstrap/lib/kernel/ebin/kernel_config.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/net_kernel.beam b/bootstrap/lib/kernel/ebin/net_kernel.beam
index 8c8786eeb9..451d054667 100644
--- a/bootstrap/lib/kernel/ebin/net_kernel.beam
+++ b/bootstrap/lib/kernel/ebin/net_kernel.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam
index df333e054e..1291f1cdfa 100644
--- a/bootstrap/lib/kernel/ebin/os.beam
+++ b/bootstrap/lib/kernel/ebin/os.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/packages.beam b/bootstrap/lib/kernel/ebin/packages.beam
index c507624578..511c6a6e74 100644
--- a/bootstrap/lib/kernel/ebin/packages.beam
+++ b/bootstrap/lib/kernel/ebin/packages.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/pg2.beam b/bootstrap/lib/kernel/ebin/pg2.beam
index 4e6817fc97..439bbc24f2 100644
--- a/bootstrap/lib/kernel/ebin/pg2.beam
+++ b/bootstrap/lib/kernel/ebin/pg2.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/rpc.beam b/bootstrap/lib/kernel/ebin/rpc.beam
index 19391982e8..4355f300e9 100644
--- a/bootstrap/lib/kernel/ebin/rpc.beam
+++ b/bootstrap/lib/kernel/ebin/rpc.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/standard_error.beam b/bootstrap/lib/kernel/ebin/standard_error.beam
index e0232d9e54..f34c1a9bd1 100644
--- a/bootstrap/lib/kernel/ebin/standard_error.beam
+++ b/bootstrap/lib/kernel/ebin/standard_error.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user.beam b/bootstrap/lib/kernel/ebin/user.beam
index df47a14304..6433bcf859 100644
--- a/bootstrap/lib/kernel/ebin/user.beam
+++ b/bootstrap/lib/kernel/ebin/user.beam
Binary files differ
diff --git a/bootstrap/lib/kernel/ebin/user_drv.beam b/bootstrap/lib/kernel/ebin/user_drv.beam
index c2b4fef911..15b09a5f93 100644
--- a/bootstrap/lib/kernel/ebin/user_drv.beam
+++ b/bootstrap/lib/kernel/ebin/user_drv.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/array.beam b/bootstrap/lib/stdlib/ebin/array.beam
index ea41ab7a42..8741e4d5df 100644
--- a/bootstrap/lib/stdlib/ebin/array.beam
+++ b/bootstrap/lib/stdlib/ebin/array.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam
index 67a8554abe..b1f5baf3b8 100644
--- a/bootstrap/lib/stdlib/ebin/beam_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/c.beam b/bootstrap/lib/stdlib/ebin/c.beam
index bd37facf37..8c69197cbc 100644
--- a/bootstrap/lib/stdlib/ebin/c.beam
+++ b/bootstrap/lib/stdlib/ebin/c.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets.beam b/bootstrap/lib/stdlib/ebin/dets.beam
index b53a1357ff..47cc5e70bb 100644
--- a/bootstrap/lib/stdlib/ebin/dets.beam
+++ b/bootstrap/lib/stdlib/ebin/dets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_server.beam b/bootstrap/lib/stdlib/ebin/dets_server.beam
index c120ee12e3..d71185c9dd 100644
--- a/bootstrap/lib/stdlib/ebin/dets_server.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam
index 0a9420daa2..a372faf6ac 100644
--- a/bootstrap/lib/stdlib/ebin/dets_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v8.beam b/bootstrap/lib/stdlib/ebin/dets_v8.beam
index 3ede6f8d47..a20f0469ce 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v8.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v8.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dets_v9.beam b/bootstrap/lib/stdlib/ebin/dets_v9.beam
index 1ac657a547..a52d126adf 100644
--- a/bootstrap/lib/stdlib/ebin/dets_v9.beam
+++ b/bootstrap/lib/stdlib/ebin/dets_v9.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/dict.beam b/bootstrap/lib/stdlib/ebin/dict.beam
index c5676edc4a..35e67d6c59 100644
--- a/bootstrap/lib/stdlib/ebin/dict.beam
+++ b/bootstrap/lib/stdlib/ebin/dict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph.beam b/bootstrap/lib/stdlib/ebin/digraph.beam
index 78814b1ad3..2c1788668d 100644
--- a/bootstrap/lib/stdlib/ebin/digraph.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
index ac2c41d2b7..a578c67e00 100644
--- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam
+++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index d809fc21f6..0cc31bcac9 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_compile.beam b/bootstrap/lib/stdlib/ebin/erl_compile.beam
index deb6b97657..1ce1d02ef0 100644
--- a/bootstrap/lib/stdlib/ebin/erl_compile.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_compile.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_eval.beam b/bootstrap/lib/stdlib/ebin/erl_eval.beam
index 6aff9793a6..3184aabc87 100644
--- a/bootstrap/lib/stdlib/ebin/erl_eval.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_eval.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
index a5431e7f04..c5c1d71941 100644
--- a/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_expand_records.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam
index c0c8cd7cdd..7b1eaf1f15 100644
--- a/bootstrap/lib/stdlib/ebin/erl_lint.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_parse.beam b/bootstrap/lib/stdlib/ebin/erl_parse.beam
index 097c378dbd..c026e8401f 100644
--- a/bootstrap/lib/stdlib/ebin/erl_parse.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_parse.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam
index 4416e29c9f..2c32b68322 100644
--- a/bootstrap/lib/stdlib/ebin/erl_pp.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam
index c331d61d21..b5e7c1c24e 100644
--- a/bootstrap/lib/stdlib/ebin/erl_scan.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/erl_tar.beam b/bootstrap/lib/stdlib/ebin/erl_tar.beam
index d9c3186502..9de0e978e3 100644
--- a/bootstrap/lib/stdlib/ebin/erl_tar.beam
+++ b/bootstrap/lib/stdlib/ebin/erl_tar.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam
index ed0e6b0d66..18066abf53 100644
--- a/bootstrap/lib/stdlib/ebin/escript.beam
+++ b/bootstrap/lib/stdlib/ebin/escript.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam
index bcd7a65cc8..8bc5103946 100644
--- a/bootstrap/lib/stdlib/ebin/ets.beam
+++ b/bootstrap/lib/stdlib/ebin/ets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam
index 95fba9495b..0c910821f6 100644
--- a/bootstrap/lib/stdlib/ebin/file_sorter.beam
+++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam
index 8137fe9570..95188a534a 100644
--- a/bootstrap/lib/stdlib/ebin/gen_event.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_event.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
index 5f46d56d18..5ee3a82cb6 100644
--- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam
index d5ab30b170..e37fa78649 100644
--- a/bootstrap/lib/stdlib/ebin/gen_server.beam
+++ b/bootstrap/lib/stdlib/ebin/gen_server.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
index ea2de10690..f7a239e18c 100644
--- a/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
+++ b/bootstrap/lib/stdlib/ebin/io_lib_pretty.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam
index f2f40ef868..5d44d3f8f1 100644
--- a/bootstrap/lib/stdlib/ebin/lib.beam
+++ b/bootstrap/lib/stdlib/ebin/lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index 3d422580e9..5e23551fb3 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/log_mf_h.beam b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
index 25a8d64b78..fdb417b71e 100644
--- a/bootstrap/lib/stdlib/ebin/log_mf_h.beam
+++ b/bootstrap/lib/stdlib/ebin/log_mf_h.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/ms_transform.beam b/bootstrap/lib/stdlib/ebin/ms_transform.beam
index 1ca5210612..1af64e9d63 100644
--- a/bootstrap/lib/stdlib/ebin/ms_transform.beam
+++ b/bootstrap/lib/stdlib/ebin/ms_transform.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/orddict.beam b/bootstrap/lib/stdlib/ebin/orddict.beam
index 76245fcd5e..6892fd2c9e 100644
--- a/bootstrap/lib/stdlib/ebin/orddict.beam
+++ b/bootstrap/lib/stdlib/ebin/orddict.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/pool.beam b/bootstrap/lib/stdlib/ebin/pool.beam
index 43c8763e8f..a16364e1d9 100644
--- a/bootstrap/lib/stdlib/ebin/pool.beam
+++ b/bootstrap/lib/stdlib/ebin/pool.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/proc_lib.beam b/bootstrap/lib/stdlib/ebin/proc_lib.beam
index 704bd8a23d..6b5c081480 100644
--- a/bootstrap/lib/stdlib/ebin/proc_lib.beam
+++ b/bootstrap/lib/stdlib/ebin/proc_lib.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam
index 4e1b8a80d1..1576557a09 100644
--- a/bootstrap/lib/stdlib/ebin/qlc.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
index 805f63930b..805203b00e 100644
--- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam
+++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/random.beam b/bootstrap/lib/stdlib/ebin/random.beam
index 1ee81ea68e..9df28216b0 100644
--- a/bootstrap/lib/stdlib/ebin/random.beam
+++ b/bootstrap/lib/stdlib/ebin/random.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/re.beam b/bootstrap/lib/stdlib/ebin/re.beam
index 22d753562d..85125291e9 100644
--- a/bootstrap/lib/stdlib/ebin/re.beam
+++ b/bootstrap/lib/stdlib/ebin/re.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sets.beam b/bootstrap/lib/stdlib/ebin/sets.beam
index a08222f3d3..5ac7691a8f 100644
--- a/bootstrap/lib/stdlib/ebin/sets.beam
+++ b/bootstrap/lib/stdlib/ebin/sets.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam
index 50a60ed5b4..2a853ea58c 100644
--- a/bootstrap/lib/stdlib/ebin/shell.beam
+++ b/bootstrap/lib/stdlib/ebin/shell.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam
index b1bc6498a6..5d9b1bd6c0 100644
--- a/bootstrap/lib/stdlib/ebin/sofs.beam
+++ b/bootstrap/lib/stdlib/ebin/sofs.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam
index 54ff535fc3..d1fe9e0cf5 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
index 2fa7bc7050..6480117b9e 100644
--- a/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
+++ b/bootstrap/lib/stdlib/ebin/supervisor_bridge.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/sys.beam b/bootstrap/lib/stdlib/ebin/sys.beam
index 499d558dc0..724dfed4e6 100644
--- a/bootstrap/lib/stdlib/ebin/sys.beam
+++ b/bootstrap/lib/stdlib/ebin/sys.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/timer.beam b/bootstrap/lib/stdlib/ebin/timer.beam
index f60983e084..5f8f714a78 100644
--- a/bootstrap/lib/stdlib/ebin/timer.beam
+++ b/bootstrap/lib/stdlib/ebin/timer.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/unicode.beam b/bootstrap/lib/stdlib/ebin/unicode.beam
index 28e3c03640..b560f13933 100644
--- a/bootstrap/lib/stdlib/ebin/unicode.beam
+++ b/bootstrap/lib/stdlib/ebin/unicode.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/zip.beam b/bootstrap/lib/stdlib/ebin/zip.beam
index 59d4697510..051c688e73 100644
--- a/bootstrap/lib/stdlib/ebin/zip.beam
+++ b/bootstrap/lib/stdlib/ebin/zip.beam
Binary files differ
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 4c84412dd6..88e8b284fb 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -285,7 +285,8 @@
<item>If E is <c><![CDATA[fun Name / Arity]]></c>, then
Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item>
<item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then
- Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.</item>
+ Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>.
+ (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item>
<item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c>
where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) =
<c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 45b66a4909..5d7ff7613b 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -1196,11 +1196,16 @@ true
</item>
<tag><c>{new_uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (a binary) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (a binary) is a unique value for this fun.
+ It is calculated from the compiled code for the entire module.</p>
</item>
<tag><c>{uniq, Uniq}</c></tag>
<item>
- <p><c>Uniq</c> (an integer) is a unique value for this fun.</p>
+ <p><c>Uniq</c> (an integer) is a unique value for this fun.
+ Starting in the R15 release, this integer is calculated from
+ the compiled code for the entire module. Before R15, this
+ integer was based on only the body of the fun.
+ </p>
</item>
</taglist>
</desc>
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 2561d7a630..8c1f85ea37 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -66,8 +66,6 @@ load_module_2(BIF_ALIST_2)
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_block_system(0);
- erts_export_consolidate();
-
hp = HAlloc(BIF_P, 3);
sz = binary_size(BIF_ARG_2);
if ((i = erts_load_module(BIF_P, 0,
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 57f5ad0a62..d82b5dbcac 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -758,6 +758,14 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
}
/*
+ * Since the literal table *may* have contained external
+ * funs (containing references to export entries), now is
+ * the time to consolidate the export tables.
+ */
+
+ erts_export_consolidate();
+
+ /*
* Load the code chunk.
*/
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 29cbdedd17..61eeec5ffd 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -25,7 +25,7 @@
t_check_process_code_ets/1,
external_fun/1,get_chunk/1,module_md5/1,make_stub/1,
make_stub_many_funs/1,constant_pools/1,
- false_dependency/1,coverage/1]).
+ false_dependency/1,coverage/1,fun_confusion/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -35,7 +35,7 @@ all() ->
[new_binary_types, t_check_process_code,
t_check_process_code_ets, t_check_old_code, external_fun, get_chunk,
module_md5, make_stub, make_stub_many_funs,
- constant_pools, false_dependency, coverage].
+ constant_pools, false_dependency, coverage, fun_confusion].
groups() ->
[].
@@ -278,7 +278,8 @@ t_check_old_code(Config) when is_list(Config) ->
external_fun(Config) when is_list(Config) ->
?line false = erlang:function_exported(another_code_test, x, 1),
- ?line ExtFun = erlang:make_fun(id(another_code_test), x, 1),
+ AnotherCodeTest = id(another_code_test),
+ ExtFun = fun AnotherCodeTest:x/1,
?line {'EXIT',{undef,_}} = (catch ExtFun(answer)),
?line false = erlang:function_exported(another_code_test, x, 1),
?line false = lists:member(another_code_test, erlang:loaded()),
@@ -555,6 +556,30 @@ coverage(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)),
ok.
+fun_confusion(Config) when is_list(Config) ->
+ Data = ?config(data_dir, Config),
+ Src = filename:join(Data, "fun_confusion"),
+ Mod = fun_confusion,
+
+ %% Load first version of module.
+ compile_load(Mod, Src, 1),
+ F1 = Mod:f(),
+ 1 = F1(),
+
+ %% Load second version of module.
+ compile_load(Mod, Src, 2),
+ F2 = Mod:f(),
+
+ %% F1 should refer to the old code, not the newly loaded code.
+ 1 = F1(),
+ 2 = F2(),
+ ok.
+
+compile_load(Mod, Src, Ver) ->
+ {ok,Mod,Code1} = compile:file(Src, [binary,{d,version,Ver}]),
+ {module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1),
+ ok.
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
diff --git a/erts/emulator/test/code_SUITE_data/fun_confusion.erl b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
new file mode 100644
index 0000000000..16000861df
--- /dev/null
+++ b/erts/emulator/test/code_SUITE_data/fun_confusion.erl
@@ -0,0 +1,31 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011. 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(fun_confusion).
+
+-export([f/0]).
+
+f() ->
+ fun() -> version() end.
+
+version() ->
+ %% Changing the value returned here should change
+ %% the identity of the fun in f/0.
+ ?version.
+
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index 6e63c4d0f2..4a9c12dfea 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -146,8 +146,10 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
Essentials0 = [AtomChunk,CodeChunk,StringChunk,ImportChunk,
ExpChunk,LambdaChunk,LiteralChunk],
- Essentials = [iolist_to_binary(C) || C <- Essentials0],
- {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, Essentials),
+ Essentials1 = [iolist_to_binary(C) || C <- Essentials0],
+ MD5 = module_md5(Essentials1),
+ Essentials = finalize_fun_table(Essentials1, MD5),
+ {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, MD5),
AttrChunk = chunk(<<"Attr">>, Attributes),
CompileChunk = chunk(<<"CInf">>, Compile),
@@ -166,6 +168,24 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, Abst, SourceFile, Opts) ->
end,
build_form(<<"BEAM">>, Chunks).
+%% finalize_fun_table(Essentials, MD5) -> FinalizedEssentials
+%% Update the 'old_uniq' field in the entry for each fun in the
+%% 'FunT' chunk. We'll use part of the MD5 for the module as a
+%% unique value.
+
+finalize_fun_table(Essentials, MD5) ->
+ [finalize_fun_table_1(E, MD5) || E <- Essentials].
+
+finalize_fun_table_1(<<"FunT",Keep:8/binary,Table0/binary>>, MD5) ->
+ <<Uniq:27,_:101/bits>> = MD5,
+ Table = finalize_fun_table_2(Table0, Uniq, <<>>),
+ <<"FunT",Keep/binary,Table/binary>>;
+finalize_fun_table_1(Chunk, _) -> Chunk.
+
+finalize_fun_table_2(<<Keep:20/binary,0:32,T/binary>>, Uniq, Acc) ->
+ finalize_fun_table_2(T, Uniq, <<Acc/binary,Keep/binary,Uniq:32>>);
+finalize_fun_table_2(<<>>, _, Acc) -> Acc.
+
%% Build an IFF form.
build_form(Id, Chunks0) when byte_size(Id) =:= 4, is_list(Chunks0) ->
@@ -202,7 +222,7 @@ flatten_exports(Exps) ->
flatten_imports(Imps) ->
list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)).
-build_attributes(Opts, SourceFile, Attr, Essentials) ->
+build_attributes(Opts, SourceFile, Attr, MD5) ->
Misc = case member(slim, Opts) of
false ->
{{Y,Mo,D},{H,Mi,S}} = erlang:universaltime(),
@@ -210,7 +230,7 @@ build_attributes(Opts, SourceFile, Attr, Essentials) ->
true -> []
end,
Compile = [{options,Opts},{version,?COMPILER_VSN}|Misc],
- {term_to_binary(calc_vsn(Attr, Essentials)),term_to_binary(Compile)}.
+ {term_to_binary(set_vsn_attribute(Attr, MD5)),term_to_binary(Compile)}.
build_line_table(Dict) ->
{NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} =
@@ -243,32 +263,30 @@ encode_line_items([], _) -> [].
%% We'll not change an existing 'vsn' attribute.
%%
-calc_vsn(Attr, Essentials0) ->
+set_vsn_attribute(Attr, MD5) ->
case keymember(vsn, 1, Attr) of
true -> Attr;
false ->
- Essentials = filter_essentials(Essentials0),
- <<Number:128>> = erlang:md5(Essentials),
+ <<Number:128>> = MD5,
[{vsn,[Number]}|Attr]
end.
+module_md5(Essentials0) ->
+ Essentials = filter_essentials(Essentials0),
+ erlang:md5(Essentials).
+
%% filter_essentials([Chunk]) -> [Chunk']
%% Filter essentials so that we obtain the same MD5 as code:module_md5/1 and
-%% beam_lib:md5/1 would calculate for this module.
+%% beam_lib:md5/1 would calculate for this module. Note that at this
+%% point, the 'old_uniq' entry for each fun in the 'FunT' chunk is zeroed,
+%% so there is no need to go through the 'FunT' chunk.
-filter_essentials([<<"FunT",_Sz:4/binary,Entries:4/binary,Table0/binary>>|T]) ->
- Table = filter_funtab(Table0, <<0:32>>),
- [Entries,Table|filter_essentials(T)];
filter_essentials([<<_Tag:4/binary,Sz:32,Data:Sz/binary,_Padding/binary>>|T]) ->
[Data|filter_essentials(T)];
filter_essentials([<<>>|T]) ->
filter_essentials(T);
filter_essentials([]) -> [].
-filter_funtab(<<Important:20/binary,_OldUniq:4/binary,T/binary>>, Zero) ->
- [Important,Zero|filter_funtab(T, Zero)];
-filter_funtab(<<>>, _) -> [].
-
bif_type(fnegate, 1) -> {op,fnegate};
bif_type(fadd, 2) -> {op,fadd};
bif_type(fsub, 2) -> {op,fsub};
@@ -310,8 +328,8 @@ make_op({test,Cond,Fail,Ops}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail|Ops], Dict);
make_op({test,Cond,Fail,Live,[Op|Ops],Dst}, Dict) when is_list(Ops) ->
encode_op(Cond, [Fail,Op,Live|Ops++[Dst]], Dict);
-make_op({make_fun2,{f,Lbl},Index,OldUniq,NumFree}, Dict0) ->
- {Fun,Dict} = beam_dict:lambda(Lbl, Index, OldUniq, NumFree, Dict0),
+make_op({make_fun2,{f,Lbl},_Index,_OldUniq,NumFree}, Dict0) ->
+ {Fun,Dict} = beam_dict:lambda(Lbl, NumFree, Dict0),
make_op({make_fun2,Fun}, Dict);
make_op({kill,Y}, Dict) ->
make_op({init,Y}, Dict);
diff --git a/lib/compiler/src/beam_dict.erl b/lib/compiler/src/beam_dict.erl
index ee76623976..531968b3c8 100644
--- a/lib/compiler/src/beam_dict.erl
+++ b/lib/compiler/src/beam_dict.erl
@@ -22,7 +22,7 @@
-export([new/0,opcode/2,highest_opcode/1,
atom/2,local/4,export/4,import/4,
- string/2,lambda/5,literal/2,line/2,fname/2,
+ string/2,lambda/3,literal/2,line/2,fname/2,
atom_table/1,local_table/1,export_table/1,import_table/1,
string_table/1,lambda_table/1,literal_table/1,
line_table/1]).
@@ -133,13 +133,18 @@ string(Str, Dict) when is_list(Str) ->
{NextOffset-Offset,Dict}
end.
-%% Returns the index for a funentry (adding it to the table if necessary).
-%% lambda(Lbl, Index, Uniq, NumFree, Dict) -> {Index,Dict'}
--spec lambda(label(), non_neg_integer(), integer(), non_neg_integer(), bdict()) ->
+%% Returns the index for a fun entry.
+%% lambda(Lbl, NumFree, Dict) -> {Index,Dict'}
+-spec lambda(label(), non_neg_integer(), bdict()) ->
{non_neg_integer(), bdict()}.
-lambda(Lbl, Index, OldUniq, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
+lambda(Lbl, NumFree, #asm{lambdas=Lambdas0}=Dict) ->
OldIndex = length(Lambdas0),
+ %% Set Index the same as OldIndex.
+ Index = OldIndex,
+ %% Initialize OldUniq to 0. It will be set to an unique value
+ %% based on the MD5 checksum of the BEAM code for the module.
+ OldUniq = 0,
Lambdas = [{Lbl,{OldIndex,Lbl,Index,NumFree,OldUniq}}|Lambdas0],
{OldIndex,Dict#asm{lambdas=Lambdas}}.
diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl
index 0fa1fea09f..ba9cde1de0 100644
--- a/lib/compiler/src/sys_pre_expand.erl
+++ b/lib/compiler/src/sys_pre_expand.erl
@@ -31,8 +31,6 @@
-import(ordsets, [from_list/1,add_element/2,union/2]).
-import(lists, [member/2,foldl/3,foldr/3]).
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
-
-include("../include/erl_bits.hrl").
-record(expand, {module=[], %Module name
@@ -49,7 +47,6 @@
func=[], %Current function
arity=[], %Arity for current function
fcount=0, %Local fun count
- fun_index=0, %Global index for funs
bitdefault,
bittypes
}).
@@ -538,32 +535,34 @@ lc_tq(_Line, [], St0) ->
%% Transform an "explicit" fun {'fun', Line, {clauses, Cs}} into an
%% extended form {'fun', Line, {clauses, Cs}, Info}, unless it is the
%% name of a BIF (erl_lint has checked that it is not an import).
-%% Process the body sequence directly to get the new and used variables.
%% "Implicit" funs {'fun', Line, {function, F, A}} are not changed.
fun_tq(Lf, {function,F,A}=Function, St0) ->
- {As,St1} = new_vars(A, Lf, St0),
- Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
case erl_internal:bif(F, A) of
true ->
+ {As,St1} = new_vars(A, Lf, St0),
+ Cs = [{clause,Lf,As,[],[{call,Lf,{atom,Lf,F},As}]}],
fun_tq(Lf, {clauses,Cs}, St1);
false ->
- Index = St0#expand.fun_index,
- Uniq = erlang:hash(Cs, (1 bsl 27)-1),
- {Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,Function,{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}
+ {Fname,St1} = new_fun_name(St0),
+ Index = Uniq = 0,
+ {{'fun',Lf,Function,{Index,Uniq,Fname}},St1}
end;
-fun_tq(L, {function,M,F,A}, St) ->
- {{call,L,{remote,L,{atom,L,erlang},{atom,L,make_fun}},
- [{atom,L,M},{atom,L,F},{integer,L,A}]},St};
+fun_tq(L, {function,M,F,A}, St) when is_atom(M), is_atom(F), is_integer(A) ->
+ %% This is the old format for external funs, generated by a pre-R15
+ %% compiler. That means that a tool, such as the debugger or xref,
+ %% directly invoked this module with the abstract code from a
+ %% pre-R15 BEAM file. Be helpful, and translate it to the new format.
+ fun_tq(L, {function,{atom,L,M},{atom,L,F},{integer,L,A}}, St);
+fun_tq(Lf, {function,_,_,_}=ExtFun, St) ->
+ {{'fun',Lf,ExtFun},St};
fun_tq(Lf, {clauses,Cs0}, St0) ->
- Uniq = erlang:hash(Cs0, (1 bsl 27)-1),
{Cs1,St1} = fun_clauses(Cs0, St0),
- Index = St1#expand.fun_index,
{Fname,St2} = new_fun_name(St1),
- {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},
- St2#expand{fun_index=Index+1}}.
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
+ {{'fun',Lf,{clauses,Cs1},{Index,Uniq,Fname}},St2}.
fun_clauses([{clause,L,H0,G0,B0}|Cs0], St0) ->
{H,St1} = head(H0, St0),
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 6f3590b156..6885405ae0 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -573,6 +573,13 @@ expr({'catch',L,E0}, St0) ->
expr({'fun',L,{function,F,A},{_,_,_}=Id}, St) ->
Lanno = lineno_anno(L, St),
{#c_var{anno=Lanno++[{id,Id}],name={F,A}},[],St};
+expr({'fun',L,{function,M,F,A}}, St0) ->
+ {As,Aps,St1} = safe_list([M,F,A], St0),
+ Lanno = lineno_anno(L, St1),
+ {#icall{anno=#a{anno=Lanno},
+ module=#c_literal{val=erlang},
+ name=#c_literal{val=make_fun},
+ args=As},Aps,St1};
expr({'fun',L,{clauses,Cs},Id}, St) ->
fun_tq(Id, Cs, L, St);
expr({call,L,{remote,_,M,F},As0}, #core{wanted=Wanted}=St0) ->
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index 4e06b464a4..47e5e49a76 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -84,8 +84,6 @@
keymember/3,keyfind/3]).
-import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]).
--compile({nowarn_deprecated_function, {erlang,hash,2}}).
-
-include("core_parse.hrl").
-include("v3_kernel.hrl").
@@ -1658,31 +1656,31 @@ uexpr(#k_catch{anno=A,body=B0}, {break,Rs0}, St0) ->
{Ns,St3} = new_vars(1 - length(Rs0), St2),
Rs1 = Rs0 ++ Ns,
{#k_catch{anno=#k{us=Bu,ns=lit_list_vars(Rs1),a=A},body=B1,ret=Rs1},Bu,St3};
-uexpr(#ifun{anno=A,vars=Vs,body=B0}=IFun, {break,Rs}, St0) ->
+uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) ->
{B1,Bu,St1} = ubody(B0, return, St0), %Return out of new function
Ns = lit_list_vars(Vs),
Free = subtract(Bu, Ns), %Free variables in fun
Fvs = make_vars(Free),
Arity = length(Vs) + length(Free),
- {{Index,Uniq,Fname}, St3} =
+ {Fname,St} =
case lists:keyfind(id, 1, A) of
- {id,Id} ->
- {Id, St1};
+ {id,{_,_,Fname0}} ->
+ {Fname0,St1};
false ->
- %% No id annotation. Must invent one.
- I = St1#kern.fcount,
- U = erlang:hash(IFun, (1 bsl 27)-1),
- {N, St2} = new_fun_name(St1),
- {{I,U,N}, St2}
+ %% No id annotation. Must invent a fun name.
+ new_fun_name(St1)
end,
Fun = #k_fdef{anno=#k{us=[],ns=[],a=A},func=Fname,arity=Arity,
vars=Vs ++ Fvs,body=B1},
+ %% Set dummy values for Index and Uniq -- the real values will
+ %% be assigned by beam_asm.
+ Index = Uniq = 0,
{#k_bif{anno=#k{us=Free,ns=lit_list_vars(Rs),a=A},
op=#k_internal{name=make_fun,arity=length(Free)+3},
args=[#k_atom{val=Fname},#k_int{val=Arity},
#k_int{val=Index},#k_int{val=Uniq}|Fvs],
ret=Rs},
- Free,add_local_function(Fun, St3)};
+ Free,add_local_function(Fun, St)};
uexpr(Lit, {break,Rs}, St) ->
%% Transform literals to puts here.
%%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]),
diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl
index 368a5815bf..6067ee8e06 100644
--- a/lib/compiler/test/fun_SUITE.erl
+++ b/lib/compiler/test/fun_SUITE.erl
@@ -20,7 +20,11 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
- test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1]).
+ test1/1,overwritten_fun/1,otp_7202/1,bif_fun/1,
+ external/1]).
+
+%% Internal export.
+-export([call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -28,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
test_lib:recompile(?MODULE),
- [test1, overwritten_fun, otp_7202, bif_fun].
+ [test1,overwritten_fun,otp_7202,bif_fun,external].
groups() ->
[].
@@ -45,7 +49,6 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
-
%%% The help functions below are copied from emulator:bs_construct_SUITE.
-define(T(B, L), {B, ??B, L}).
@@ -152,4 +155,47 @@ bif_fun(Config) when is_list(Config) ->
?line F = fun abs/1,
?line 5 = F(-5),
ok.
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/compiler/test/pmod_SUITE.erl b/lib/compiler/test/pmod_SUITE.erl
index 9a317b5762..3d02adaf52 100644
--- a/lib/compiler/test/pmod_SUITE.erl
+++ b/lib/compiler/test/pmod_SUITE.erl
@@ -96,6 +96,10 @@ basic_1(Config, Opts) ->
?line error = Prop4:bar_bar({s,a,b}),
?line error = Prop4:bar_bar([]),
+ %% Call from a fun.
+ Fun = fun(Arg) -> Prop4:bar(Arg) end,
+ ?line ok = Fun({s,0}),
+
ok.
otp_8447(Config) when is_list(Config) ->
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index df725ed9e5..2e88c35741 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -768,6 +768,21 @@ expr({make_fun,Line,Name,Cs}, Bs, #ieval{module=Module}=Ieval) ->
end,
{value,Fun,Bs};
+%% Construct an external fun.
+expr({make_ext_fun,Line,MFA0}, Bs0, Ieval0) ->
+ {[M,F,A],Bs} = eval_list(MFA0, Bs0, Ieval0),
+ try erlang:make_fun(M, F, A) of
+ Value ->
+ {value,Value,Bs}
+ catch
+ error:badarg ->
+ Ieval1 = Ieval0#ieval{line=Line},
+ Ieval2 = dbg_istk:push(Bs0, Ieval1, false),
+ Ieval = Ieval2#ieval{module=erlang,function=make_fun,
+ arguments=[M,F,A],line=-1},
+ exception(error, badarg, Bs, Ieval, true)
+ end;
+
%% Common test adaptation
expr({call_remote,0,ct_line,line,As0,Lc}, Bs0, Ieval0) ->
{As,_Bs} = eval_list(As0, Bs0, Ieval0),
diff --git a/lib/debugger/src/dbg_iload.erl b/lib/debugger/src/dbg_iload.erl
index ce5631e45f..3c95ef8068 100644
--- a/lib/debugger/src/dbg_iload.erl
+++ b/lib/debugger/src/dbg_iload.erl
@@ -369,6 +369,14 @@ expr({'fun',Line,{function,F,A},{_Index,_OldUniq,Name}}, _Lc) ->
As = new_vars(A, Line),
Cs = [{clause,Line,As,[],[{local_call,Line,F,As,true}]}],
{make_fun,Line,Name,Cs};
+expr({'fun',Line,{function,{atom,_,M},{atom,_,F},{integer,_,A}}}, _Lc)
+ when 0 =< A, A =< 255 ->
+ %% New format in R15 for fun M:F/A (literal values).
+ {value,Line,erlang:make_fun(M, F, A)};
+expr({'fun',Line,{function,M,F,A}}, _Lc) ->
+ %% New format in R15 for fun M:F/A (one or more variables).
+ MFA = expr_list([M,F,A]),
+ {make_ext_fun,Line,MFA};
expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,self}},[]}, _Lc) ->
{dbg,Line,self,[]};
expr({call,Line,{remote,_,{atom,_,erlang},{atom,_,get_stacktrace}},[]}, _Lc) ->
diff --git a/lib/debugger/test/fun_SUITE.erl b/lib/debugger/test/fun_SUITE.erl
index 8103d9c692..a06cdc7165 100644
--- a/lib/debugger/test/fun_SUITE.erl
+++ b/lib/debugger/test/fun_SUITE.erl
@@ -24,8 +24,10 @@
init_per_testcase/2,end_per_testcase/2,
init_per_suite/1,end_per_suite/1,
good_call/1,bad_apply/1,bad_fun_call/1,badarity/1,
- ext_badarity/1,otp_6061/1]).
--export([nothing/0]).
+ ext_badarity/1,otp_6061/1,external/1]).
+
+%% Internal exports.
+-export([nothing/0,call_me/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -46,7 +48,7 @@ end_per_group(_GroupName, Config) ->
cases() ->
[good_call, bad_apply, bad_fun_call, badarity,
- ext_badarity, otp_6061].
+ ext_badarity, otp_6061, external].
init_per_testcase(_Case, Config) ->
test_lib:interpret(?MODULE),
@@ -244,3 +246,47 @@ test_otp_6061(Starter) ->
fun() -> Starter ! working end,
fun() -> Starter ! not_working end],
lists:foreach(fun(P)->(lists:nth(P,PassesF))() end,Passes).
+
+-define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)).
+-define(APPLY2(M, F, A),
+ (fun(Map) ->
+ Id = fun(I) -> I end,
+ List = [x,y],
+ List = Map(Id, List),
+ {type,external} = erlang:fun_info(Map, type)
+ end)(fun M:F/A)).
+
+external(Config) when is_list(Config) ->
+ Mod = id(?MODULE),
+ Func = id(call_me),
+ Arity = id(1),
+
+ ?APPLY(?MODULE, call_me, 1),
+ ?APPLY(?MODULE, call_me, Arity),
+ ?APPLY(?MODULE, Func, 1),
+ ?APPLY(?MODULE, Func, Arity),
+ ?APPLY(Mod, call_me, 1),
+ ?APPLY(Mod, call_me, Arity),
+ ?APPLY(Mod, Func, 1),
+ ?APPLY(Mod, Func, Arity),
+
+ ListsMod = id(lists),
+ ListsMap = id(map),
+ ListsArity = id(2),
+
+ ?APPLY2(lists, map, 2),
+ ?APPLY2(lists, map, ListsArity),
+ ?APPLY2(lists, ListsMap, 2),
+ ?APPLY2(lists, ListsMap, ListsArity),
+ ?APPLY2(ListsMod, map, 2),
+ ?APPLY2(ListsMod, map, ListsArity),
+ ?APPLY2(ListsMod, ListsMap, 2),
+ ?APPLY2(ListsMod, ListsMap, ListsArity),
+
+ ok.
+
+call_me(I) ->
+ {ok,I}.
+
+id(I) ->
+ I.
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 72f02a4362..95a5efd6d0 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -154,18 +154,23 @@ decipher(?AES, HashSz, CipherState, Fragment, Version) ->
block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
HashSz, Fragment, Version) ->
- try Fun(Key, IV, Fragment) of
- Text ->
- GBC = generic_block_cipher_from_bin(Text, HashSz),
- case is_correct_padding(GBC, Version) of
- true ->
- Content = GBC#generic_block_cipher.content,
- Mac = GBC#generic_block_cipher.mac,
- CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
- {Content, Mac, CipherState1};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end
+ try
+ Text = Fun(Key, IV, Fragment),
+ GBC = generic_block_cipher_from_bin(Text, HashSz),
+ Content = GBC#generic_block_cipher.content,
+ Mac = GBC#generic_block_cipher.mac,
+ CipherState1 = CipherState0#cipher_state{iv=next_iv(Fragment, IV)},
+ case is_correct_padding(GBC, Version) of
+ true ->
+ {Content, Mac, CipherState1};
+ false ->
+ %% decryption failed or invalid padding,
+ %% intentionally break Content to make
+ %% sure a packet with a an invalid padding
+ %% but otherwise correct data will fail
+ %% the MAC test later
+ {<<16#F0, Content/binary>>, Mac, CipherState1}
+ end
catch
_:_ ->
%% This is a DECRYPTION_FAILED but
@@ -500,14 +505,38 @@ hash_size(md5) ->
hash_size(sha) ->
20.
+%% RFC 5246: 6.2.3.2. CBC Block Cipher
+%%
+%% Implementation note: Canvel et al. [CBCTIME] have demonstrated a
+%% timing attack on CBC padding based on the time required to compute
+%% the MAC. In order to defend against this attack, implementations
+%% MUST ensure that record processing time is essentially the same
+%% whether or not the padding is correct. In general, the best way to
+%% do this is to compute the MAC even if the padding is incorrect, and
+%% only then reject the packet. For instance, if the pad appears to be
+%% incorrect, the implementation might assume a zero-length pad and then
+%% compute the MAC. This leaves a small timing channel, since MAC
+%% performance depends to some extent on the size of the data fragment,
+%% but it is not believed to be large enough to be exploitable, due to
+%% the large block size of existing MACs and the small size of the
+%% timing signal.
+%%
+%% implementation note:
+%% We return the original (possibly invalid) PadLength in any case.
+%% A invalid PadLength will be cought by is_correct_padding/2
+%%
generic_block_cipher_from_bin(T, HashSize) ->
Sz1 = byte_size(T) - 1,
- <<_:Sz1/binary, ?BYTE(PadLength)>> = T,
+ <<_:Sz1/binary, ?BYTE(PadLength0)>> = T,
+ PadLength = if
+ PadLength0 >= Sz1 -> 0;
+ true -> PadLength0
+ end,
CompressedLength = byte_size(T) - PadLength - 1 - HashSize,
<<Content:CompressedLength/binary, Mac:HashSize/binary,
- Padding:PadLength/binary, ?BYTE(PadLength)>> = T,
+ Padding:PadLength/binary, ?BYTE(PadLength0)>> = T,
#generic_block_cipher{content=Content, mac=Mac,
- padding=Padding, padding_length=PadLength}.
+ padding=Padding, padding_length=PadLength0}.
generic_stream_cipher_from_bin(T, HashSz) ->
Sz = byte_size(T),
@@ -516,17 +545,18 @@ generic_stream_cipher_from_bin(T, HashSz) ->
#generic_stream_cipher{content=Content,
mac=Mac}.
-is_correct_padding(_, {3, 0}) ->
- true;
-%% For interoperability reasons we do not check the padding in TLS 1.0 as it
-%% is not strictly required and breaks interopability with for instance
-%% Google.
-is_correct_padding(_, {3, 1}) ->
- true;
+%% For interoperability reasons we do not check the padding content in
+%% SSL 3.0 and TLS 1.0 as it is not strictly required and breaks
+%% interopability with for instance Google.
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, {3, N})
+ when N == 0; N == 1 ->
+ Len == byte_size(Padding);
%% Padding must be check in TLS 1.1 and after
-is_correct_padding(#generic_block_cipher{padding_length = Len, padding = Padding}, _) ->
- list_to_binary(lists:duplicate(Len, Len)) == Padding.
-
+is_correct_padding(#generic_block_cipher{padding_length = Len,
+ padding = Padding}, _) ->
+ Len == byte_size(Padding) andalso
+ list_to_binary(lists:duplicate(Len, Len)) == Padding.
get_padding(Length, BlockSize) ->
get_padding_aux(BlockSize, Length rem BlockSize).
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 23a9a23190..6b1da63d08 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -39,6 +39,7 @@ MODULES = \
ssl_basic_SUITE \
ssl_handshake_SUITE \
ssl_packet_SUITE \
+ ssl_cipher_SUITE \
ssl_payload_SUITE \
ssl_to_openssl_SUITE \
ssl_session_cache_SUITE \
@@ -55,6 +56,7 @@ HRL_FILES_SRC = \
ssl_internal.hrl\
ssl_alert.hrl \
ssl_handshake.hrl \
+ ssl_cipher.hrl \
ssl_record.hrl
HRL_FILES_INC =
diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl
new file mode 100644
index 0000000000..87478e13bc
--- /dev/null
+++ b/lib/ssl/test/ssl_cipher_SUITE.erl
@@ -0,0 +1,163 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2011. 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(ssl_cipher_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
+-include("ssl_cipher.hrl").
+
+-define(TIMEOUT, 600000).
+
+%% Test server callback functions
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config) -> Config
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Initialization before the whole suite
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ try crypto:start() of
+ ok ->
+ Config
+ catch _:_ ->
+ {skip, "Crypto did not start"}
+ end.
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> _
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after the whole suite
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ssl:stop(),
+ application:stop(crypto).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config) -> Config
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Initialization before each test case
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%% Description: Initialization before each test case
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config0) ->
+ Config = lists:keydelete(watchdog, 1, Config0),
+ Dog = ssl_test_lib:timetrap(?TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> _
+%% Case - atom()
+%% Name of the test case that is about to be run.
+%% Config - [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Description: Cleanup after each test case
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, Config) ->
+ Dog = ?config(watchdog, Config),
+ case Dog of
+ undefined ->
+ ok;
+ _ ->
+ test_server:timetrap_cancel(Dog)
+ end.
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> TestCases
+%% Clause - atom() - suite | doc
+%% TestCases - [Case]
+%% Case - atom()
+%% Name of a test case.
+%% Description: Returns a list of all test cases in this test suite
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [aes_decipher_good, aes_decipher_fail].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+
+%% Test cases starts here.
+%%--------------------------------------------------------------------
+aes_decipher_good(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_good(suite) ->
+ [];
+
+aes_decipher_good(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,148>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,3},
+ Content = <<183,139,16,132,10,209,67,86,168,100,61,217,145,57,36,56,72,69,76,76,79,10>>,
+ Mac = <<71,136,212,107,223,200,70,232,127,116,148,205,232,35,158,113,237,174,15,217,192,168,35,8,6,107,107,233,25,174,90,111>>,
+ {Content, Mac, CipherState1} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ ok.
+
+%%--------------------------------------------------------------------
+
+aes_decipher_fail(doc) ->
+ ["Decipher a known cryptotext."];
+
+aes_decipher_fail(suite) ->
+ [];
+
+%% same as above, last byte of key replaced
+aes_decipher_fail(Config) when is_list(Config) ->
+ HashSz = 32,
+ CipherState = #cipher_state{iv = <<59,201,85,117,188,206,224,136,5,109,46,70,104,79,4,9>>,
+ key = <<72,196,247,97,62,213,222,109,210,204,217,186,172,184,197,254>>},
+ Fragment = <<220,193,179,139,171,33,143,245,202,47,123,251,13,232,114,8,
+ 190,162,74,31,186,227,119,155,94,74,119,79,169,193,240,160,
+ 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122,
+ 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>,
+ Version = {3,3},
+ {Content, Mac, CipherState1} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version),
+ 32 = byte_size(Content),
+ 32 = byte_size(Mac),
+ ok.
+
+%%--------------------------------------------------------------------
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl
index b63acdd40a..72e41d6473 100644
--- a/lib/stdlib/examples/erl_id_trans.erl
+++ b/lib/stdlib/examples/erl_id_trans.erl
@@ -419,7 +419,14 @@ expr({'fun',Line,Body}) ->
{'fun',Line,{clauses,Cs1}};
{function,F,A} ->
{'fun',Line,{function,F,A}};
- {function,M,F,A} -> %R10B-6: fun M:F/A.
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% R10B-6: fun M:F/A. (Backward compatibility)
+ {'fun',Line,{function,M,F,A}};
+ {function,M0,F0,A0} ->
+ %% R15: fun M:F/A with variables.
+ M = expr(M0),
+ F = expr(F0),
+ A = expr(A0),
{'fun',Line,{function,M,F,A}}
end;
expr({call,Line,F0,As0}) ->
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 4f4fa16040..88a0094d57 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -256,7 +256,8 @@ expr({'receive',_,Cs}, Bs, Lf, Ef, RBs) ->
expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs) ->
{value,T,Bs} = expr(E, Bs0, Lf, Ef, none),
receive_clauses(T, Cs, {TB,Bs}, Bs0, Lf, Ef, [], RBs);
-expr({'fun',_Line,{function,Mod,Name,Arity}}, Bs, _Lf, _Ef, RBs) ->
+expr({'fun',_Line,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs) ->
+ {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef),
F = erlang:make_fun(Mod, Name, Arity),
ret_expr(F, Bs, RBs);
expr({'fun',_Line,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs) -> % R8
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 78b996d94b..5d45260fe9 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -2127,8 +2127,13 @@ expr({'fun',Line,Body}, Vt, St) ->
true -> {[],St};
false -> {[],call_function(Line, F, A, St)}
end;
- {function,_M,_F,_A} ->
- {[],St}
+ {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) ->
+ %% Compatibility with pre-R15 abstract format.
+ {[],St};
+ {function,M,F,A} ->
+ %% New in R15.
+ {Bvt, St1} = expr_list([M,F,A], Vt, St),
+ {vtupdate(Bvt, Vt),St1}
end;
expr({call,_Line,{atom,_Lr,is_record},[E,{atom,Ln,Name}]}, Vt, St0) ->
{Rvt,St1} = expr(E, Vt, St0),
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 709bd83e6f..928c10f7f2 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -35,7 +35,7 @@ tuple
%struct
record_expr record_tuple record_field record_fields
if_expr if_clause if_clauses case_expr cr_clause cr_clauses receive_expr
-fun_expr fun_clause fun_clauses
+fun_expr fun_clause fun_clauses atom_or_var integer_or_var
try_expr try_catch try_clause try_clauses query_expr
function_call argument_list
exprs guard
@@ -395,11 +395,17 @@ receive_expr -> 'receive' cr_clauses 'after' expr clause_body 'end' :
fun_expr -> 'fun' atom '/' integer :
{'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4')}}.
-fun_expr -> 'fun' atom ':' atom '/' integer :
- {'fun',?line('$1'),{function,element(3, '$2'),element(3, '$4'),element(3,'$6')}}.
+fun_expr -> 'fun' atom_or_var ':' atom_or_var '/' integer_or_var :
+ {'fun',?line('$1'),{function,'$2','$4','$6'}}.
fun_expr -> 'fun' fun_clauses 'end' :
build_fun(?line('$1'), '$2').
+atom_or_var -> atom : '$1'.
+atom_or_var -> var : '$1'.
+
+integer_or_var -> integer : '$1'.
+integer_or_var -> var : '$1'.
+
fun_clauses -> fun_clause : ['$1'].
fun_clauses -> fun_clause ';' fun_clauses : ['$1' | '$3'].
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 7dc19f2e9b..6b5aa951cf 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -457,8 +457,16 @@ lexpr({'fun',_,{function,F,A}}, _Prec, _Hook) ->
leaf(format("fun ~w/~w", [F,A]));
lexpr({'fun',_,{function,F,A},Extra}, _Prec, _Hook) ->
{force_nl,fun_info(Extra),leaf(format("fun ~w/~w", [F,A]))};
-lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook) ->
+lexpr({'fun',_,{function,M,F,A}}, _Prec, _Hook)
+ when is_atom(M), is_atom(F), is_integer(A) ->
+ %% For backward compatibility with pre-R15 abstract format.
leaf(format("fun ~w:~w/~w", [M,F,A]));
+lexpr({'fun',_,{function,M,F,A}}, _Prec, Hook) ->
+ %% New format in R15.
+ NameItem = lexpr(M, Hook),
+ CallItem = lexpr(F, Hook),
+ ArityItem = lexpr(A, Hook),
+ ["fun ",NameItem,$:,CallItem,$/,ArityItem];
lexpr({'fun',_,{clauses,Cs}}, _Prec, Hook) ->
{list,[{first,'fun',fun_clauses(Cs, Hook)},'end']};
lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Hook) ->
diff --git a/lib/stdlib/src/qlc.erl b/lib/stdlib/src/qlc.erl
index f5e180b4bd..2b691e6abf 100644
--- a/lib/stdlib/src/qlc.erl
+++ b/lib/stdlib/src/qlc.erl
@@ -1272,7 +1272,10 @@ abstr_term(Fun, Line) when is_function(Fun) ->
case erlang:fun_info(Fun, type) of
{type, external} ->
{module, Module} = erlang:fun_info(Fun, module),
- {'fun', Line, {function,Module,Name,Arity}};
+ {'fun', Line, {function,
+ {atom,Line,Module},
+ {atom,Line,Name},
+ {integer,Line,Arity}}};
{type, local} ->
{'fun', Line, {function,Name,Arity}}
end
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 784c7cb86e..369d8b224e 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1036,6 +1036,12 @@ funs(Config) when is_list(Config) ->
lists:usort([run_many_args(SAs) || SAs <- many_args(MaxArgs)]),
?line {'EXIT',{{argument_limit,_},_}} =
(catch run_many_args(many_args1(MaxArgs+1))),
+
+ ?line check(fun() -> M = lists, F = fun M:reverse/1,
+ [1,2] = F([2,1]), ok end,
+ "begin M = lists, F = fun M:reverse/1,"
+ " [1,2] = F([2,1]), ok end.",
+ ok),
ok.
run_many_args({S, As}) ->
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index 280c95b1aa..64853ca078 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -116,7 +116,6 @@ func(Config) when is_list(Config) ->
{func_3,
<<"t() -> fun t/0.">>},
{func_4,
- %% Has already been expanded away in sys_pre_expand.
<<"t() -> fun modul:foo/3.">>},
{func_5, % 'when' is moved down one line
<<"tkjlksjflksdjflsdjlk()
@@ -127,7 +126,9 @@ func(Config) when is_list(Config) ->
<<"t() ->
(fun() ->
true
- end)().">>}
+ end)().">>},
+ {func_7,
+ <<"t(M, F, A) -> fun M:F/A.">>}
],
?line compile(Config, Ts),
ok.
diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl
index 98eeaee118..8a9d8f7883 100644
--- a/lib/stdlib/test/qlc_SUITE.erl
+++ b/lib/stdlib/test/qlc_SUITE.erl
@@ -6632,7 +6632,7 @@ otp_7232(Config) when is_list(Config) ->
{call,_,
{remote,_,{atom,_,qlc},{atom,_,sort}},
[{cons,_,
- {'fun',_,{function,math,sqrt,_}},
+ {'fun',_,{function,{atom,_,math},{atom,_,sqrt},_}},
{cons,_,
{string,_,\"<0.4.1>\"}, % could use list_to_pid..
{cons,_,{string,_,\"#Ref<\"++_},{nil,_}}}},
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 9df5f26454..7f58fda519 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -6093,11 +6093,16 @@ implicit_fun_name(Node) ->
{'fun', Pos, {function, Atom, Arity}} ->
arity_qualifier(set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos));
- {'fun', Pos, {function, Module, Atom, Arity}} ->
+ {'fun', Pos, {function, Module, Atom, Arity}}
+ when is_atom(Module), is_atom(Atom), is_integer(Arity) ->
+ %% Backward compatibility with pre-R15 abstract format.
module_qualifier(set_pos(atom(Module), Pos),
arity_qualifier(
set_pos(atom(Atom), Pos),
set_pos(integer(Arity), Pos)));
+ {'fun', Pos, {function, Module, Atom, Arity}} ->
+ %% New in R15: fun M:F/A.
+ module_qualifier(Module, arity_qualifier(Atom, Arity));
Node1 ->
data(Node1)
end.
diff --git a/lib/tools/src/xref_reader.erl b/lib/tools/src/xref_reader.erl
index d22f0df164..92f0c45c7b 100644
--- a/lib/tools/src/xref_reader.erl
+++ b/lib/tools/src/xref_reader.erl
@@ -158,15 +158,20 @@ expr({'try',_Line,Es,Scs,Ccs,As}, S) ->
S2 = clauses(Scs, S1),
S3 = clauses(Ccs, S2),
expr(As, S3);
-expr({call, Line,
- {remote, _, {atom,_,erlang}, {atom,_,make_fun}},
- [{atom,_,Mod}, {atom,_,Fun}, {integer,_,Arity}]}, S) ->
- %% Added in R10B-6. M:F/A.
- expr({'fun', Line, {function, Mod, Fun, Arity}}, S);
-expr({'fun', Line, {function, Mod, Name, Arity}}, S) ->
- %% Added in R10B-6. M:F/A.
+expr({'fun', Line, {function, {atom,_,Mod},
+ {atom,_,Name},
+ {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (literals).
As = lists:duplicate(Arity, {atom, Line, foo}),
external_call(Mod, Name, As, Line, false, S);
+expr({'fun', Line, {function, Mod, Name, {integer,_,Arity}}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = lists:duplicate(Arity, {atom, Line, foo}),
+ external_call(erlang, apply, [Mod, Name, list2term(As)], Line, true, S);
+expr({'fun', Line, {function, Mod, Name, _Arity}}, S) ->
+ %% New format in R15. M:F/A (one or more variables).
+ As = {var, Line, '_'},
+ external_call(erlang, apply, [Mod, Name, As], Line, true, S);
expr({'fun', Line, {function, Name, Arity}, _Extra}, S) ->
%% Added in R8.
handle_call(local, S#xrefr.module, Name, Arity, Line, S);
@@ -286,10 +291,10 @@ check_funarg(W, ArgsList, Line, S) ->
expr(ArgsList, S1).
funarg({'fun', _, _Clauses, _Extra}, _S) -> true;
-funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
-funarg({call,_,{remote,_,{atom,_,erlang},{atom,_,make_fun}},_MFA}, _S) ->
- %% R10B-6. M:F/A.
+funarg({'fun', _, {function,_,_,_}}, _S) ->
+ %% New abstract format for fun M:F/A in R15.
true;
+funarg({var, _, Var}, S) -> member(Var, S#xrefr.funvars);
funarg(_, _S) -> false.
fun_args(apply2, [FunArg, Args]) -> {FunArg, Args};
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index fe7f92de78..881a3c2997 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -583,21 +583,14 @@ otp_6115_1(Config) ->
%% called -- running cover compiled code when there is no cover
%% server and thus no ets tables to bump counters in, makes no
%% sense.
- ?line Pid1 = f1:start_fail(),
-
- %% If f1 is cover compiled, a process P is started with a
- %% reference to the fun created in start_ok/0, and
- %% cover:stop() is called, then P should survive.
- %% This is because (the fun held by) P always references the current
- %% version of the module, and is thus not affected by the cover
- %% compiled version being unloaded.
- ?line Pid2 = f1:start_ok(),
+ Pid1 = f1:start_a(),
+ Pid2 = f1:start_b(),
%% Now stop cover
?line cover:stop(),
- %% Ensure that f1 is loaded (and not cover compiled), that Pid1
- %% is dead and Pid2 is alive, but with no reference to old code
+ %% Ensure that f1 is loaded (and not cover compiled), and that
+ %% both Pid1 and Pid2 are dead.
case code:which(f1) of
Beam when is_list(Beam) ->
ok;
@@ -608,19 +601,15 @@ otp_6115_1(Config) ->
undefined ->
ok;
_PI1 ->
- RefToOldP = erlang:check_process_code(Pid1, f1),
- ?line ?t:fail({"Pid1 still alive", RefToOldP})
+ RefToOldP1 = erlang:check_process_code(Pid1, f1),
+ ?t:fail({"Pid1 still alive", RefToOldP1})
end,
case process_info(Pid2) of
- PI2 when is_list(PI2) ->
- case erlang:check_process_code(Pid2, f2) of
- false ->
- ok;
- true ->
- ?line ?t:fail("Pid2 has ref to old code")
- end;
undefined ->
- ?line ?t:fail("Pid2 has died")
+ ok;
+ _PI2 ->
+ RefToOldP2 = erlang:check_process_code(Pid1, f2),
+ ?t:fail({"Pid2 still alive", RefToOldP2})
end,
?line file:set_cwd(CWD),
diff --git a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
index b659e5d818..5399b33f19 100644
--- a/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
+++ b/lib/tools/test/cover_SUITE_data/otp_6115/f1.erl
@@ -1,12 +1,13 @@
-module(f1).
--export([start_fail/0, start_ok/0]).
+-export([start_a/0, start_b/0]).
-start_fail() ->
+start_a() ->
f2:start(fun() ->
- io:format("this does not work\n",[])
+ ok
end).
-start_ok() ->
+start_b() ->
f2:start(fun fun1/0).
+
fun1() ->
- io:format("this works\n",[]).
+ ok.
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 2f83ab4995..e0876381ca 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -46,7 +46,8 @@
-export([
add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1,
replace/1, update/1, deprecated/1, trycatch/1,
- abstract_modules/1, fun_mfa/1, qlc/1]).
+ abstract_modules/1, fun_mfa/1, fun_mfa_r14/1,
+ fun_mfa_vars/1, qlc/1]).
-export([
analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]).
@@ -82,7 +83,7 @@ groups() ->
{files, [],
[add, default, info, lib, read, read2, remove, replace,
update, deprecated, trycatch, abstract_modules, fun_mfa,
- qlc]},
+ fun_mfa_r14, fun_mfa_vars, qlc]},
{analyses, [],
[analyze, basic, md, q, variables, unused_locals]},
{misc, [], [format_error, otp_7423, otp_7831]}].
@@ -1771,6 +1772,88 @@ fun_mfa(Conf) when is_list(Conf) ->
?line ok = file:delete(Beam),
ok.
+%% Same as the previous test case, except that we use a BEAM file
+%% that was compiled by an R14 compiler to test backward compatibility.
+fun_mfa_r14(Conf) when is_list(Conf) ->
+ Dir = ?config(data_dir, Conf),
+ MFile = fname(Dir, "fun_mfa_r14"),
+
+ A = fun_mfa_r14,
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]},
+ {{{A,t,0},{A,t,0}},[6]},
+ {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]},
+ {{{A,t1,0},{A,t,0}},[10]},
+ {{{A,t2,0},{A,t,0}},[14]},
+ {{{A,t3,0},{A,t3,0}},[17]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok.
+
+%% fun M:F/A with varibles.
+fun_mfa_vars(Conf) when is_list(Conf) ->
+ Dir = ?copydir,
+ File = fname(Dir, "fun_mfa_vars.erl"),
+ MFile = fname(Dir, "fun_mfa_vars"),
+ Beam = fname(Dir, "fun_mfa_vars.beam"),
+ Test = <<"-module(fun_mfa_vars).
+
+ -export([t/1, t1/1, t2/3]).
+
+ t(Mod) ->
+ F = fun Mod:bar/2,
+ (F)(a, b).
+
+ t1(Name) ->
+ F = fun ?MODULE:Name/1,
+ (F)(a).
+
+ t2(Mod, Name, Arity) ->
+ F = fun Mod:Name/Arity,
+ (F)(a).
+
+ t3(Arity) ->
+ F = fun ?MODULE:t/Arity,
+ (F)(1, 2, 3).
+
+ t4(Mod, Name) ->
+ F = fun Mod:Name/3,
+ (F)(a, b, c).
+
+ t5(Mod, Arity) ->
+ F = fun Mod:t/Arity,
+ (F)().
+ ">>,
+
+ ok = file:write_file(File, Test),
+ A = fun_mfa_vars,
+ {ok, A} = compile:file(File, [report,debug_info,{outdir,Dir}]),
+ {ok, _} = xref:start(s),
+ {ok, A} = xref:add_module(s, MFile, {warnings,false}),
+ {ok, [{{{A,t,1},{'$M_EXPR','$F_EXPR',2}},[7]},
+ {{{A,t,1},{'$M_EXPR',bar,2}},[6]},
+ {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]},
+ {{{A,t1,1},{A,'$F_EXPR',1}},[10]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]},
+ {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]},
+ {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]},
+ {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]},
+ {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]},
+ {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]},
+ {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} =
+ xref:q(s, "(Lin) E"),
+
+ ok = check_state(s),
+ xref:stop(s),
+
+ ok = file:delete(File),
+ ok = file:delete(Beam),
+ ok.
+
qlc(suite) -> [];
qlc(doc) -> ["OTP-5195: A bug fix when using qlc:q/1,2."];
qlc(Conf) when is_list(Conf) ->
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
new file mode 100644
index 0000000000..4645525690
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.beam
Binary files differ
diff --git a/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
new file mode 100644
index 0000000000..293bd83a8b
--- /dev/null
+++ b/lib/tools/test/xref_SUITE_data/fun_mfa_r14.erl
@@ -0,0 +1,18 @@
+-module(fun_mfa_r14).
+
+-export([t/0, t1/0, t2/0, t3/0]).
+
+t() ->
+ F = fun ?MODULE:t/0,
+ (F)().
+
+t1() ->
+ F = fun t/0,
+ (F)().
+
+t2() ->
+ fun ?MODULE:t/0().
+
+t3() ->
+ fun t3/0().
+
diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml
index f56e1ff408..3ea72a4057 100644
--- a/system/doc/reference_manual/code_loading.xml
+++ b/system/doc/reference_manual/code_loading.xml
@@ -112,8 +112,8 @@ loop() ->
<c>code_switch</c> to it. The process then will make a fully
qualified call to <c>m:loop()</c> and change to current code.
Note that <c>m:loop/0</c> must be exported.</p>
- <p>For code replacement of funs to work, the tuple syntax
- <c>{Module,FunctionName}</c> must be used to represent the fun.</p>
+ <p>For code replacement of funs to work, the syntax
+ <c>fun Module:FunctionName/Arity</c> should be used.</p>
</section>
<section>
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index c24b1110a4..43d46d87cc 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -993,15 +993,19 @@ fun Module:Name/Arity</pre>
<pre>
fun (Arg1,...,ArgN) -> Name(Arg1,...,ArgN) end</pre>
<p>In <c>Module:Name/Arity</c>, <c>Module</c> and <c>Name</c> are atoms
- and <c>Arity</c> is an integer.
+ and <c>Arity</c> is an integer. Starting from the R15 release,
+ <c>Module</c>, <c>Name</c>, and <c>Arity</c> may also be variables.
A fun defined in this way will refer to the function <c>Name</c>
- with arity <c>Arity</c> in the <em>latest</em> version of module <c>Module</c>.
+ with arity <c>Arity</c> in the <em>latest</em> version of module
+ <c>Module</c>. A fun defined in this way will not be dependent on
+ the code for module in which it is defined.
</p>
<p>When applied to a number N of arguments, a tuple
<c>{Module,FunctionName}</c> is interpreted as a fun, referring
to the function <c>FunctionName</c> with arity N in the module
<c>Module</c>. The function must be exported.
- <em>This usage is deprecated.</em>
+ <em>This usage is deprecated.</em> Use <c>fun Module:Name/Arity</c>
+ instead.
See <seealso marker="#calls">Function Calls</seealso> for an example.</p>
<p>More examples can be found in <em>Programming Examples</em>.</p>
</section>