Skip to content

Commit

Permalink
Merge branch 'bjorn/compiler/fix-clean/erlangGH-6169/OTP-18183' into …
Browse files Browse the repository at this point in the history
…maint

* bjorn/compiler/fix-clean/erlangGH-6169/OTP-18183:
  Eliminate compiler crash in beam_clean
  • Loading branch information
bjorng committed Jul 27, 2022
2 parents b07a112 + d431f40 commit 6c942e4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
19 changes: 16 additions & 3 deletions lib/compiler/src/beam_call_types.erl
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@
%%
%% Returns whether a call will succeed or not.
%%
%% Note that it only answers 'yes' for functions in the 'erlang' module as
%% Notes:
%%
%% This function only answers 'yes' for functions in the 'erlang' module as
%% calls to other modules may fail due to not being loaded, even if we consider
%% the module to be known.
%%
%% This function MUST return 'no' if types/3 with the same arguments will return
%% the return type 'none'.
%%

-spec will_succeed(Mod, Func, ArgTypes) -> Result when
Mod :: atom(),
Expand Down Expand Up @@ -161,13 +166,21 @@ succeeds_if_type(ArgType, Required) ->
succeeds_if_smallish(#t_integer{elements={Min,Max}})
when abs(Min) bsr 128 =:= 0, abs(Max) bsr 128 =:= 0 ->
yes;
succeeds_if_smallish(_) ->
'maybe'.
succeeds_if_smallish(ArgType) ->
case succeeds_if_type(ArgType, number) of
yes ->
%% Could potentially fail with a `system_limit` exception.
'maybe';
Other ->
Other
end.

succeeds_if_smallish(LHS, RHS) ->
case {succeeds_if_smallish(LHS),
succeeds_if_smallish(RHS)} of
{yes, yes} -> yes;
{no, _} -> no;
{_, no} -> no;
{_, _} -> 'maybe'
end.

Expand Down
20 changes: 18 additions & 2 deletions lib/compiler/test/beam_type_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1,
none_argument/1,success_type_oscillation/1,type_subtraction/1,
container_subtraction/1,is_list_opt/1,connected_tuple_elements/1,
switch_fail_inference/1]).
switch_fail_inference/1,failures/1]).

%% Force id/1 to return 'any'.
-export([id/1]).
Expand Down Expand Up @@ -62,7 +62,8 @@ groups() ->
container_subtraction,
is_list_opt,
connected_tuple_elements,
switch_fail_inference
switch_fail_inference,
failures
]}].

init_per_suite(Config) ->
Expand Down Expand Up @@ -911,5 +912,20 @@ sfi_send_return_value({304}) ->
sfi_send_return_value({412}) ->
error.

failures(_Config) ->
{'EXIT',{function_clause,_}} = catch failures_1(id(a), id(b), id(c)),
{'EXIT',{badarith,_}} = catch failures_1([], 2, 3),
{'EXIT',{badarith,_}} = catch failures_1([], x, y),
ok.

failures_1([] = V1, V2, V3) ->
%% beam_call_types:types(erlang, '-', [any,nil]) would return
%% {none,_,_}, indicating that the call would fail, while
%% beam_call_types:will_succeed/3 called with the same arguments
%% would return `maybe` instead of `no`. That would cause
%% generation of incorrect BEAM code that would ultimately cause
%% beam_clean to crash.
{V1 - V3, (V1 = V2) - V3}.

id(I) ->
I.

0 comments on commit 6c942e4

Please sign in to comment.