File 6661-erts-Support-missing-guard-BIFs-like-is_boolean-1-in.patch of Package erlang
From 1b78756047c2b7a1c55e58ba19dce60e65fd29da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Thu, 23 Mar 2023 09:14:37 +0100
Subject: [PATCH] erts: Support missing guard BIFs like is_boolean/1 in match
specs
---
erts/doc/src/match_spec.xml | 38 +++++++++-------
erts/emulator/beam/erl_db_util.c | 60 ++++++++++++++++++++-----
erts/emulator/test/match_spec_SUITE.erl | 37 +++++++++++++--
3 files changed, 104 insertions(+), 31 deletions(-)
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml
index 81b30efec8..a62eef43c4 100644
--- a/erts/doc/src/match_spec.xml
+++ b/erts/doc/src/match_spec.xml
@@ -87,7 +87,8 @@
<c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> |
<c><![CDATA[is_map]]></c> | <c><![CDATA[is_map_key]]></c> |
- <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_function]]></c> |
+ <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_bitstring]]></c> |
+ <c><![CDATA[is_boolean]]></c> | <c><![CDATA[is_function]]></c> |
<c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> |
<c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> |
<c><![CDATA['not']]></c> | <c><![CDATA['xor']]></c> |
@@ -113,11 +114,12 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> |
<c><![CDATA[max]]></c> | <c><![CDATA[min]]></c> |
- <c><![CDATA[node]]></c> |
- <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
+ <c><![CDATA[node]]></c> | <c><![CDATA[float]]></c> |
+ <c><![CDATA[round]]></c> | <c><![CDATA[floor]]></c> |
+ <c><![CDATA[ceil]]></c> | <c><![CDATA[size]]></c> |
<c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c> |
- <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
- <c><![CDATA[binary_part]]></c> |
+ <c><![CDATA[tuple_size]]></c> | <c><![CDATA[tl]]></c> |
+ <c><![CDATA[trunc]]></c> | <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -173,8 +175,9 @@
<c><![CDATA[is_list]]></c> | <c><![CDATA[is_number]]></c> |
<c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> |
<c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> |
- <c><![CDATA[is_map]]></c> | <c><![CDATA[map_is_key]]></c> |
- <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_function]]></c> |
+ <c><![CDATA[is_map]]></c> | <c><![CDATA[is_map_key]]></c> |
+ <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_bitstring]]></c> |
+ <c><![CDATA[is_boolean]]></c> | <c><![CDATA[is_function]]></c> |
<c><![CDATA[is_record]]></c> | <c><![CDATA['and']]></c> |
<c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> |
<c><![CDATA['xor']]></c> | <c><![CDATA['andalso']]></c> |
@@ -199,11 +202,12 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> |
<c><![CDATA[max]]></c> | <c><![CDATA[min]]></c> |
- <c><![CDATA[node]]></c> |
- <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
+ <c><![CDATA[node]]></c> | <c><![CDATA[float]]></c> |
+ <c><![CDATA[round]]></c> | <c><![CDATA[floor]]></c> |
+ <c><![CDATA[ceil]]></c> | <c><![CDATA[size]]></c> |
<c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c> |
- <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
- <c><![CDATA[binary_part]]></c> |
+ <c><![CDATA[tuple_size]]></c> | <c><![CDATA[tl]]></c> |
+ <c><![CDATA[trunc]]></c> | <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -228,9 +232,10 @@
follows:</p>
<taglist>
- <tag><c>is_atom</c>, <c>is_float</c>, <c>is_integer</c>, <c>is_list</c>,
- <c>is_number</c>, <c>is_pid</c>, <c>is_port</c>, <c>is_reference</c>,
- <c>is_tuple</c>, <c>is_map</c>, <c>is_binary</c>, <c>is_function</c>
+ <tag><c>is_atom</c>, <c>is_boolean</c>, <c>is_float</c>,
+ <c>is_integer</c>, <c>is_list</c>, <c>is_number</c>, <c>is_pid</c>,
+ <c>is_port</c>, <c>is_reference</c>, <c>is_tuple</c>, <c>is_map</c>,
+ <c>is_binary</c>, <c>is_bitstring</c>, <c>is_function</c>
</tag>
<item>
<p>Same as the corresponding guard tests in Erlang, return
@@ -281,8 +286,9 @@
<tag><c>abs</c>, <c>element</c>, <c>hd</c>, <c>length</c>,
<c>map_get</c>, <c>map_size</c>,
<c>max</c>, <c>min</c>,
- <c>node</c>, <c>round</c>,
- <c>size</c>, <c>bit_size</c>, <c>byte_size</c>, <c>tl</c>,
+ <c>node</c>, <c>round</c>, <c>ceil</c>, <c>floor</c>, <c>float</c>,
+ <c>size</c>, <c>bit_size</c>, <c>byte_size</c>, <c>tuple_size</c>,
+ <c>tl</c>,
<c>trunc</c>, <c>binary_part</c>, <c>'+'</c>,
<c>'-'</c>, <c>'*'</c>, <c>'div'</c>, <c>'rem'</c>, <c>'band'</c>,
<c>'bor'</c>, <c>'bxor'</c>, <c>'bnot'</c>, <c>'bsl'</c>,
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 4290d8506f..38d755f7f6 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -589,16 +589,34 @@ static DMCGuardBif guard_tab[] =
DBIF_ALL
},
{
- am_is_binary,
- &is_binary_1,
- 1,
- DBIF_ALL
+ am_is_binary,
+ &is_binary_1,
+ 1,
+ DBIF_ALL
},
{
- am_is_function,
- &is_function_1,
- 1,
- DBIF_ALL
+ am_is_bitstring,
+ &is_bitstring_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_is_boolean,
+ &is_boolean_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_is_function,
+ &is_function_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_is_function,
+ &is_function_2,
+ 2,
+ DBIF_ALL
},
{
am_is_record,
@@ -696,6 +714,12 @@ static DMCGuardBif guard_tab[] =
1,
DBIF_ALL
},
+ {
+ am_tuple_size,
+ &tuple_size_1,
+ 1,
+ DBIF_ALL
+ },
{
am_binary_part,
&binary_part_2,
@@ -721,10 +745,22 @@ static DMCGuardBif guard_tab[] =
DBIF_ALL
},
{
- am_float,
- &float_1,
- 1,
- DBIF_ALL
+ am_float,
+ &float_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_ceil,
+ &ceil_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_floor,
+ &floor_1,
+ 1,
+ DBIF_ALL
},
{
am_Plus,
diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl
index 18df432836..43e475b125 100644
--- a/erts/emulator/test/match_spec_SUITE.erl
+++ b/erts/emulator/test/match_spec_SUITE.erl
@@ -28,7 +28,8 @@
ms_trace2/1, ms_trace3/1, ms_trace_dead/1, boxed_and_small/1,
destructive_in_test_bif/1, guard_exceptions/1,
empty_list/1,
- unary_plus/1, unary_minus/1, moving_labels/1]).
+ unary_plus/1, unary_minus/1, moving_labels/1,
+ guard_bifs/1]).
-export([fpe/1]).
-export([otp_9422/1]).
-export([faulty_seq_trace/1, do_faulty_seq_trace/0]).
@@ -57,7 +58,8 @@ all() ->
faulty_seq_trace,
empty_list,
otp_9422,
- maps].
+ maps,
+ guard_bifs].
init_per_testcase(_TestCase, Config) ->
Config.
@@ -1145,7 +1147,36 @@ moving_labels(Config) when is_list(Config) ->
erlang:match_spec_test({true,false}, Ms2, table),
ok.
-
+
+-record(dummy_record, {}).
+
+%% GH-7045: Some guard BIFs were unavailable in match specifications.
+guard_bifs(_Config) ->
+ Matches =
+ [begin
+ BIF = list_to_tuple([F | lists:duplicate(A, '$1')]),
+ erlang:match_spec_test(Data, [{{'$1'}, [BIF], [{{'$1'}}]}], Kind)
+ end
+ || {F, A} <- erlang:module_info(functions),
+ {Data, Kind} <- [{{a}, table}, {[a], trace}],
+ F =/= is_record, %% Has special requirements, checked below.
+ erl_internal:arith_op(F, A) orelse
+ erl_internal:bool_op(F, A) orelse
+ erl_internal:comp_op(F, A) orelse
+ erl_internal:guard_bif(F, A)],
+ [] = [T || {error, _}=T <- Matches],
+
+ IsRecord = {is_record,
+ '$1',
+ dummy_record,
+ record_info(size, dummy_record)},
+ [{ok, _, [], []} =
+ erlang:match_spec_test(Data, [{{'$1'}, [IsRecord], [{{'$1'}}]}], Kind)
+ || {Data, Kind} <- [{{#dummy_record{}}, table},
+ {[#dummy_record{}], trace}]],
+
+ ok.
+
tr(Fun, MFA, Pat, Expected) ->
tr(Fun, MFA, [call], Pat, [global], Expected).
--
2.35.3