Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
4241-erts-Add-types-nonempty_-binary-bitstring....
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 4241-erts-Add-types-nonempty_-binary-bitstring.patch of Package erlang
From 00b83732b17755d4a2ee1dab36401e52b0c6105c Mon Sep 17 00:00:00 2001 From: Hans Bolinder <hasse@erlang.org> Date: Wed, 21 Apr 2021 14:14:37 +0200 Subject: [PATCH] erts: Add types nonempty_{binary,bitstring}() See also GH-4636. --- lib/dialyzer/src/erl_types.erl | 28 +++++++++++ .../test/indent2_SUITE_data/results/iodata | 13 ++---- lib/dialyzer/test/r9c_SUITE_data/results/asn1 | 4 +- .../small_SUITE_data/results/binary_nonempty | 16 +++++++ .../small_SUITE_data/results/binary_redef2 | 3 ++ .../small_SUITE_data/src/binary_nonempty.erl | 46 +++++++++++++++++++ .../small_SUITE_data/src/binary_redef.erl | 22 +++++++++ .../small_SUITE_data/src/binary_redef2.erl | 23 ++++++++++ .../test/specdiffs_SUITE_data/results/iodata | 2 +- .../test/user_SUITE_data/results/wsp_pdu | 2 +- lib/edoc/src/edoc_types.erl | 2 + lib/stdlib/src/erl_internal.erl | 2 + lib/stdlib/src/erl_lint.erl | 3 ++ lib/stdlib/test/erl_lint_SUITE.erl | 20 +++++++- system/doc/reference_manual/typespec.xml | 6 +++ 15 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/binary_nonempty create mode 100644 lib/dialyzer/test/small_SUITE_data/results/binary_redef2 create mode 100644 lib/dialyzer/test/small_SUITE_data/src/binary_nonempty.erl create mode 100644 lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl create mode 100644 lib/dialyzer/test/small_SUITE_data/src/binary_redef2.erl diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 12f4b450a4..dc5ea7ab82 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -167,6 +167,8 @@ t_nil/0, t_node/0, t_none/0, + t_nonempty_binary/0, + t_nonempty_bitstring/0, t_nonempty_list/0, t_nonempty_list/1, t_nonempty_string/0, @@ -928,6 +930,11 @@ is_boolean(_) -> false. t_binary() -> ?bitstr(8, 0). +-spec t_nonempty_binary() -> erl_type(). + +t_nonempty_binary() -> + ?bitstr(8, 8). + -spec t_is_binary(erl_type()) -> boolean(). t_is_binary(Type) -> @@ -951,6 +958,11 @@ is_binary(_) -> false. t_bitstr() -> ?bitstr(1, 0). +-spec t_nonempty_bitstring() -> erl_type(). + +t_nonempty_bitstring() -> + ?bitstr(1, 1). + -spec t_bitstr(non_neg_integer(), non_neg_integer()) -> erl_type(). t_bitstr(U, B) -> @@ -4471,8 +4483,12 @@ t_to_string(?bitstr(0, 0), _RecDict) -> "<<>>"; t_to_string(?bitstr(8, 0), _RecDict) -> "binary()"; +t_to_string(?bitstr(8, 8), _RecDict) -> + "nonempty_binary()"; t_to_string(?bitstr(1, 0), _RecDict) -> "bitstring()"; +t_to_string(?bitstr(1, 1), _RecDict) -> + "nonempty_bitstring()"; t_to_string(?bitstr(0, B), _RecDict) -> flat_format("<<_:~w>>", [B]); t_to_string(?bitstr(U, 0), _RecDict) -> @@ -4945,6 +4961,14 @@ from_form({type, _L, node, []}, _S, _D, {t_node(), L, C}; from_form({type, _L, none, []}, _S, _D, L, C) -> {t_none(), L, C}; +from_form({type, _L, nonempty_binary, []}, S, D, L, C) -> + try type_from_form(nonempty_binary, [], S, D, L, C) + catch _:_ -> {t_nonempty_binary(), L, C} + end; +from_form({type, _L, nonempty_bitstring, []}, S, D, L, C) -> + try type_from_form(nonempty_binary, [], S, D, L, C) + catch _:_ -> {t_nonempty_bitstring(), L, C} + end; from_form({type, _L, nonempty_list, []}, _S, _D, L, C) -> {t_nonempty_list(), L, C}; from_form({type, _L, nonempty_list, [Type]}, S, D, L, C) -> @@ -5549,6 +5573,10 @@ t_form_to_string({type, _L, map_field_ex t_form_to_string({type, _L, mfa, []}) -> "mfa()"; t_form_to_string({type, _L, module, []}) -> "module()"; t_form_to_string({type, _L, node, []}) -> "node()"; +t_form_to_string({type, _L, nonempty_binary, []}) -> + "nonempty_binary()"; +t_form_to_string({type, _L, nonempty_bitstring, []}) -> + "nonempty_bitstring()"; t_form_to_string({type, _L, nonempty_list, [Type]}) -> "[" ++ t_form_to_string(Type) ++ ",...]"; t_form_to_string({type, _L, nonempty_string, []}) -> "nonempty_string()"; diff --git a/lib/dialyzer/test/indent2_SUITE_data/results/iodata b/lib/dialyzer/test/indent2_SUITE_data/results/iodata index 88e1b9b34c..0ffb8cffc3 100644 --- a/lib/dialyzer/test/indent2_SUITE_data/results/iodata +++ b/lib/dialyzer/test/indent2_SUITE_data/results/iodata @@ -1,19 +1,16 @@ iodata.erl:7: The specification for iodata:encode/2 states that the function might also return binary() but the inferred return is - nonempty_maybe_improper_list(<<_:8, _:_*8>> | - nonempty_maybe_improper_list(<<_:8, - _:_*8>> | + nonempty_maybe_improper_list(nonempty_binary() | + nonempty_maybe_improper_list(nonempty_binary() | nonempty_maybe_improper_list(any(), - <<_:8, - _:_*8>> | + nonempty_binary() | []) | byte(), - <<_:8, - _:_*8>> | + nonempty_binary() | []) | integer(), - <<_:8, _:_*8>> | []) | + nonempty_binary() | []) | integer() iodata.erl:7: The success typing for iodata:encode/2 implies that the function might also return integer() but the specification return is diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 index a56f57a8e4..e73698747c 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/asn1 +++ b/lib/dialyzer/test/r9c_SUITE_data/results/asn1 @@ -75,7 +75,7 @@ asn1rt_per.erl:1237: The call erlang:'not'('implemented') will never return s asn1rt_per.erl:989: The pattern <_C, 'true', _Val> can never match the type <_,'false',_> asn1rt_per_bin.erl:1361: The pattern <_, 'true', _> can never match the type <_,'false',_> asn1rt_per_bin.erl:1436: The pattern {'BMPString', {'octets', Ol}} can never match the type {'BMPString' | 'IA5String' | 'NumericString' | 'PrintableString' | 'UniversalString' | 'VisibleString',[{'bits',1 | 2 | 4 | 8 | 16 | 32,_}]} -asn1rt_per_bin.erl:161: The call asn1rt_per_bin:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>}) +asn1rt_per_bin.erl:161: The call asn1rt_per_bin:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (nonempty_binary() | {non_neg_integer(),nonempty_bitstring()}) asn1rt_per_bin.erl:1812: The pattern {Name, Val} can never match since previous clauses completely covered the type any() asn1rt_per_bin.erl:2106: Cons will produce an improper list since its 2nd argument is binary() asn1rt_per_bin.erl:2111: Cons will produce an improper list since its 2nd argument is binary() @@ -90,7 +90,7 @@ asn1rt_per_bin.erl:467: The variable _ can never match since previous clauses asn1rt_per_bin.erl:474: The pattern <{_N, <<_,Bs/binary>>}, C> can never match since previous clauses completely covered the type <{0,_},integer()> asn1rt_per_bin.erl:487: The variable _ can never match since previous clauses completely covered the type integer() asn1rt_per_bin.erl:498: The variable _ can never match since previous clauses completely covered the type integer() -asn1rt_per_bin_rt2ct.erl:152: The call asn1rt_per_bin_rt2ct:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>> | {non_neg_integer(),<<_:1,_:_*1>>}) +asn1rt_per_bin_rt2ct.erl:152: The call asn1rt_per_bin_rt2ct:getbit({0,maybe_improper_list()}) will never return since it differs in the 1st argument from the success typing arguments: (nonempty_binary() | {non_neg_integer(),nonempty_bitstring()}) asn1rt_per_bin_rt2ct.erl:1533: The pattern {'BMPString', {'octets', Ol}} can never match the type {_,[[any(),...]]} asn1rt_per_bin_rt2ct.erl:1875: The pattern {Name, Val} can never match since previous clauses completely covered the type any() asn1rt_per_bin_rt2ct.erl:443: The variable _ can never match since previous clauses completely covered the type integer() diff --git a/lib/dialyzer/test/small_SUITE_data/results/binary_nonempty b/lib/dialyzer/test/small_SUITE_data/results/binary_nonempty new file mode 100644 index 0000000000..5275482a59 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/binary_nonempty @@ -0,0 +1,16 @@ + +binary_nonempty.erl:12: Function t2/0 has no local return +binary_nonempty.erl:13: The call binary_nonempty:t2(<<>>) breaks the contract (nonempty_binary()) -> 'foo' +binary_nonempty.erl:15: Invalid type specification for function binary_nonempty:t2/1. The success typing is (<<>>) -> 'foo' +binary_nonempty.erl:19: Function t3/0 has no local return +binary_nonempty.erl:20: The call binary_nonempty:t3(<<>>) breaks the contract (<<_:1,_:_*1>>) -> 'foo' +binary_nonempty.erl:22: Invalid type specification for function binary_nonempty:t3/1. The success typing is (<<>>) -> 'foo' +binary_nonempty.erl:26: Function t4/0 has no local return +binary_nonempty.erl:27: The call binary_nonempty:t4(<<>>) breaks the contract (<<_:8,_:_*8>>) -> 'foo' +binary_nonempty.erl:29: Invalid type specification for function binary_nonempty:t4/1. The success typing is (<<>>) -> 'foo' +binary_nonempty.erl:33: Invalid type specification for function binary_nonempty:t5/1. The success typing is (<<>>) -> 'foo' +binary_nonempty.erl:38: Invalid type specification for function binary_nonempty:t6/1. The success typing is (<<_:8>>) -> 'foo' +binary_nonempty.erl:43: Invalid type specification for function binary_nonempty:t7/1. The success typing is (<<_:1>>) -> 'foo' +binary_nonempty.erl:5: Function t1/0 has no local return +binary_nonempty.erl:6: The call binary_nonempty:t1(<<>>) breaks the contract (nonempty_bitstring()) -> 'foo' +binary_nonempty.erl:8: Invalid type specification for function binary_nonempty:t1/1. The success typing is (<<>>) -> 'foo' diff --git a/lib/dialyzer/test/small_SUITE_data/results/binary_redef2 b/lib/dialyzer/test/small_SUITE_data/results/binary_redef2 new file mode 100644 index 0000000000..71968b801b --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/binary_redef2 @@ -0,0 +1,3 @@ + +binary_redef2.erl:15: Invalid type specification for function binary_redef2:t1/1. The success typing is (3) -> 6 +binary_redef2.erl:20: Invalid type specification for function binary_redef2:new/0. The success typing is () -> 3 diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_nonempty.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_nonempty.erl new file mode 100644 index 0000000000..da1e0ba466 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/binary_nonempty.erl @@ -0,0 +1,46 @@ +-module(binary_nonempty). + +-export([t1/0, t2/0, t3/0, t4/0, t5/1, t6/1, t7/1]). + +t1() -> + t1(<<>>). + +-spec t1(nonempty_bitstring()) -> foo. +t1(_B) -> + foo. + +t2() -> + t2(<<>>). + +-spec t2(nonempty_binary()) -> foo. +t2(_B) -> + foo. + +t3() -> + t3(<<>>). + +-spec t3(<<_:1, _:_*1>>) -> foo. +t3(_B) -> + foo. + +t4() -> + t4(<<>>). + +-spec t4(<<_:8, _:_*8>>) -> foo. +t4(_B) -> + foo. + +-spec t5(nonempty_binary()) -> foo. +t5(B) -> + <<>> = B, + foo. + +-spec t6(<<>>) -> foo. +t6(B) -> + B = <<"f">>, % The type is <<_:8>>. + foo. + +-spec t7(<<>>) -> foo. +t7(B) -> + B = <<1:1>>, % The type is <<_:1>>. + foo. diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl new file mode 100644 index 0000000000..851b8180d3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/binary_redef.erl @@ -0,0 +1,22 @@ +-module(binary_redef). + +-export([t/0]). + +-export_type([nonempty_binary/0, nonempty_bitstring/0]). + +-type nonempty_binary() :: integer(). +-type nonempty_bitstring() :: integer(). + +t() -> + I = new(), + t1(I). + +-spec t1(nonempty_bitstring()) -> nonempty_bitstring(). + +t1(A) -> + A + A. + +-spec new() -> nonempty_binary(). + +new() -> + 3. diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_redef2.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_redef2.erl new file mode 100644 index 0000000000..6ce871e540 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/binary_redef2.erl @@ -0,0 +1,23 @@ +-module(binary_redef2). + +-export([t/0]). + +-export_type([nonempty_binary/0, nonempty_bitstring/0]). + +%% Use the builtin types. +%%-type nonempty_binary() :: integer(). +%%-type nonempty_bitstring() :: integer(). + +t() -> + I = new(), + t1(I). + +-spec t1(nonempty_bitstring()) -> nonempty_bitstring(). + +t1(A) -> + A + A. + +-spec new() -> nonempty_binary(). + +new() -> + 3. diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata b/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata index d6e24fe277..1d0f967090 100644 --- a/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata +++ b/lib/dialyzer/test/specdiffs_SUITE_data/results/iodata @@ -1,3 +1,3 @@ -iodata.erl:7: The specification for iodata:encode/2 states that the function might also return binary() but the inferred return is nonempty_maybe_improper_list(<<_:8,_:_*8>> | nonempty_maybe_improper_list(<<_:8,_:_*8>> | nonempty_maybe_improper_list(any(),<<_:8,_:_*8>> | []) | byte(),<<_:8,_:_*8>> | []) | integer(),<<_:8,_:_*8>> | []) | integer() +iodata.erl:7: The specification for iodata:encode/2 states that the function might also return binary() but the inferred return is nonempty_maybe_improper_list(nonempty_binary() | nonempty_maybe_improper_list(nonempty_binary() | nonempty_maybe_improper_list(any(),nonempty_binary() | []) | byte(),nonempty_binary() | []) | integer(),nonempty_binary() | []) | integer() iodata.erl:7: The success typing for iodata:encode/2 implies that the function might also return integer() but the specification return is binary() | maybe_improper_list(binary() | maybe_improper_list(any(),binary() | []) | byte(),binary() | []) diff --git a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu index 73a2c3b339..64e28aa47b 100644 --- a/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu +++ b/lib/dialyzer/test/user_SUITE_data/results/wsp_pdu @@ -8,7 +8,7 @@ wsp_pdu.erl:2408:3: The pattern {'short', Data2} can never match the type {[byte wsp_pdu.erl:2755: Function parse_push_flag/1 has no local return wsp_pdu.erl:2756: The call erlang:integer_to_list(Value::[any()]) breaks the contract (Integer) -> string() when Integer :: integer() wsp_pdu.erl:2875: The call wsp_pdu:d_text_string(Data::byte()) will never return since it differs in the 1st argument from the success typing arguments: (binary()) -wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (<<_:8,_:_*8>>) +wsp_pdu.erl:2976: The call wsp_pdu:d_q_value(QData::byte()) will never return since it differs in the 1st argument from the success typing arguments: (nonempty_binary()) wsp_pdu.erl:3336: The call wsp_pdu:encode_typed_field(Ver::any(),'Q-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any()) wsp_pdu.erl:3342: The call wsp_pdu:encode_typed_field(Ver::any(),'Ver-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any()) wsp_pdu.erl:3349: The call wsp_pdu:encode_typed_field(Ver::any(),'Integer-value',ParamValue::any()) will never return since it differs in the 2nd argument from the success typing arguments: (any(),'Constrained-encoding' | 'Date-value' | 'No-value' | 'Short-integer' | 'Text-string' | 'Text-value' | 'Well-known-charset',any()) diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl index 51219b5143..9da447bec5 100644 --- a/lib/edoc/src/edoc_types.erl +++ b/lib/edoc/src/edoc_types.erl @@ -137,6 +137,8 @@ is_predefined(cons, 2) -> true; is_predefined(deep_string, 0) -> true; is_predefined(F, A) -> erl_internal:is_type(F, A). +is_new_predefined(nonempty_binary, 0) -> true; +is_new_predefined(nonempty_bitstring, 0) -> true; is_new_predefined(map, 0) -> true; is_new_predefined(_, _) -> false. diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl index 682b49f3c4..e3ee8a8b9f 100644 --- a/lib/stdlib/src/erl_internal.erl +++ b/lib/stdlib/src/erl_internal.erl @@ -582,6 +582,8 @@ is_type(no_return, 0) -> true; is_type(node, 0) -> true; is_type(non_neg_integer, 0) -> true; is_type(none, 0) -> true; +is_type(nonempty_binary, 0) -> true; +is_type(nonempty_bitstring, 0) -> true; is_type(nonempty_improper_list, 2) -> true; is_type(nonempty_list, 0) -> true; is_type(nonempty_list, 1) -> true; diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 157e7ecbd4..e3bb694629 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -3100,6 +3100,9 @@ used_type(TypePair, Anno, #lint{usage = Usage, file = File} = St) -> is_default_type({Name, NumberOfTypeVariables}) -> erl_internal:is_type(Name, NumberOfTypeVariables). +%% OTP 24.0 +is_newly_introduced_builtin_type({nonempty_binary, 0}) -> true; +is_newly_introduced_builtin_type({nonempty_bitstring, 0}) -> true; is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. is_obsolete_builtin_type(TypePair) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 69b9b7dc42..39f4964e06 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -69,7 +69,7 @@ stacktrace_syntax/1, otp_14285/1, otp_14378/1, external_funs/1,otp_15456/1,otp_15563/1, - unused_type/1,removed/1, otp_16516/1, + unused_type/1,binary_types/1,removed/1, otp_16516/1, inline_nifs/1, warn_missing_spec/1, unused_record/1]). @@ -96,7 +96,7 @@ all() -> otp_11851, otp_11879, otp_13230, record_errors, otp_11879_cont, non_latin1_module, otp_14323, stacktrace_syntax, otp_14285, otp_14378, external_funs, - otp_15456, otp_15563, unused_type, removed, otp_16516, + otp_15456, otp_15563, unused_type, binary_types, removed, otp_16516, inline_nifs, warn_missing_spec, unused_record]. @@ -953,6 +953,22 @@ unused_type(Config) when is_list(Config) -> [] = run(Config, Ts), ok. +%% OTP-17301. Types nonempty_binary(), nonempty_bitstring(). +binary_types(Config) when is_list(Config) -> + Ts = [{binary1, + <<"-type nonempty_binary() :: term().">>, + [nowarn_unused_type], + {warnings,[{{1,22},erl_lint, + {new_builtin_type,{nonempty_binary,0}}}]}}, + + {binary2, + <<"-type nonempty_bitstring() :: term().">>, + [nowarn_unused_type], + {warnings,[{{1,22},erl_lint, + {new_builtin_type,{nonempty_bitstring,0}}}]}}], + [] = run(Config, Ts), + ok. + %% OTP-4671. Errors for unsafe variables. unsafe_vars(Config) when is_list(Config) -> Ts = [{unsafe1, diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index c800301edc..dcd76468fb 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -218,9 +218,15 @@ <row> <cell><c>binary()</c></cell><cell><c><<_:_*8>></c></cell> </row> + <row> + <cell><c>nonempty_binary()</c></cell><cell><c><<_:8, _:_*8>></c></cell> + </row> <row> <cell><c>bitstring()</c></cell><cell><c><<_:_*1>></c></cell> </row> + <row> + <cell><c>nonempty_bitstring()</c></cell><cell><c><<_:1, _:_*1>></c></cell> + </row> <row> <cell><c>boolean()</c></cell><cell><c>'false' | 'true'</c></cell> </row> -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor