From 119e72d3e766089dc7347b75d0530b0c626cff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 9 May 2019 13:22:24 +0200 Subject: Fix compiler crash when funs were matched Code such as the following would crash the compiler in OTP 22: [some_atom = fun some_function/1] The reason is that the fun would be copied (used both in the match operation and as a value in the list), and the copy of the fun would create two wrapper functions with the same name for calling some_function/1. In OTP 21, the duplicate functions happened not to cause any harm (one of the wrappers functions would be unused and ultimately be removed by beam_clean). In OTP 22, the new beam_ssa_type pass would be confused by the multiple definitions of the wrapper function. --- lib/compiler/src/v3_core.erl | 3 ++- lib/compiler/test/fun_SUITE.erl | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 3699c9d22e..007a0247f4 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1811,7 +1811,8 @@ force_safe(Ce, St0) -> is_safe(#c_cons{}) -> true; is_safe(#c_tuple{}) -> true; -is_safe(#c_var{}) -> true; +is_safe(#c_var{name={_,_}}) -> false; %Fun. Not safe. +is_safe(#c_var{name=_}) -> true; %Ordinary variable. is_safe(#c_literal{}) -> true; is_safe(_) -> false. diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl index 1df0a05275..7fc6195e31 100644 --- a/lib/compiler/test/fun_SUITE.erl +++ b/lib/compiler/test/fun_SUITE.erl @@ -22,7 +22,8 @@ -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, - external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1]). + external/1,eep37/1,eep37_dup/1,badarity/1,badfun/1, + duplicated_fun/1]). %% Internal exports. -export([call_me/1,dup1/0,dup2/0]). @@ -37,7 +38,7 @@ all() -> groups() -> [{p,[parallel], [test1,overwritten_fun,otp_7202,bif_fun,external,eep37, - eep37_dup,badarity,badfun]}]. + eep37_dup,badarity,badfun,duplicated_fun]}]. init_per_suite(Config) -> test_lib:recompile(?MODULE), @@ -261,5 +262,20 @@ badfun(_Config) -> expect_badfun(Term, Exit) -> {'EXIT',{{badfun,Term},_}} = Exit. +duplicated_fun(_Config) -> + try + %% The following code used to crash the compiler before + %% v3_core:is_safe/1 was corrected to consider fun variables + %% unsafe. + id([print_result_paths_fun = fun duplicated_fun_helper/1]), + ct:error(should_fail) + catch + error:{badmatch,F} when is_function(F, 1) -> + ok + end. + +duplicated_fun_helper(_) -> + ok. + id(I) -> I. -- cgit v1.2.3