From d94b28b7a919c427a14805494662804c3fcf5c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 Apr 2019 05:40:00 +0200 Subject: Don't warn for removed functions in OTP 18 or older --- lib/stdlib/src/otp_internal.erl | 142 ------------------------------------- lib/stdlib/test/erl_lint_SUITE.erl | 5 +- 2 files changed, 2 insertions(+), 145 deletions(-) diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index b95cb8f525..f31356968e 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -323,90 +323,6 @@ obsolete_1(snmp, N, A) -> obsolete_1(snmpa, old_info_format, 1) -> {deprecated, "Deprecated; (will be removed in OTP 18); use \"new\" format instead"}; -obsolete_1(snmpm, agent_info, 3) -> - {removed, {snmpm, agent_info, 2}, "R16B"}; -obsolete_1(snmpm, update_agent_info, 5) -> - {removed, {snmpm, update_agent_info, 4}, "R16B"}; -obsolete_1(snmpm, g, 3) -> - {removed, {snmpm, sync_get, 3}, "R16B"}; -obsolete_1(snmpm, g, 4) -> - {removed, {snmpm, sync_get, [3,4]}, "R16B"}; -obsolete_1(snmpm, g, 5) -> - {removed, {snmpm, sync_get, [4,5]}, "R16B"}; -obsolete_1(snmpm, g, 6) -> - {removed, {snmpm, sync_get, [5,6]}, "R16B"}; -obsolete_1(snmpm, g, 7) -> - {removed, {snmpm, sync_get, 6}, "R16B"}; -obsolete_1(snmpm, ag, 3) -> - {removed, {snmpm, async_get, 3}, "R16B"}; -obsolete_1(snmpm, ag, 4) -> - {removed, {snmpm, async_get, [3,4]}, "R16B"}; -obsolete_1(snmpm, ag, 5) -> - {removed, {snmpm, async_get, [4,5]}, "R16B"}; -obsolete_1(snmpm, ag, 6) -> - {removed, {snmpm, async_get, [5,6]}, "R16B"}; -obsolete_1(snmpm, ag, 7) -> - {removed, {snmpm, async_get, 6}, "R16B"}; -obsolete_1(snmpm, gn, 3) -> - {removed, {snmpm, sync_get_next, 3}, "R16B"}; -obsolete_1(snmpm, gn, 4) -> - {removed, {snmpm, sync_get_next, [3,4]}, "R16B"}; -obsolete_1(snmpm, gn, 5) -> - {removed, {snmpm, sync_get_next, [4,5]}, "R16B"}; -obsolete_1(snmpm, gn, 6) -> - {removed, {snmpm, sync_get_next, [5,6]}, "R16B"}; -obsolete_1(snmpm, gn, 7) -> - {removed, {snmpm, sync_get_next, 6}, "R16B"}; -obsolete_1(snmpm, agn, 3) -> - {removed, {snmpm, async_get_next, 3}, "R16B"}; -obsolete_1(snmpm, agn, 4) -> - {removed, {snmpm, async_get_next, [3,4]}, "R16B"}; -obsolete_1(snmpm, agn, 5) -> - {removed, {snmpm, async_get_next, [4,5]}, "R16B"}; -obsolete_1(snmpm, agn, 6) -> - {removed, {snmpm, async_get_next, [5,6]}, "R16B"}; -obsolete_1(snmpm, agn, 7) -> - {removed, {snmpm, async_get_next, 6}, "R16B"}; -obsolete_1(snmpm, s, 3) -> - {removed, {snmpm, sync_set, 3}, "R16B"}; -obsolete_1(snmpm, s, 4) -> - {removed, {snmpm, sync_set, [3,4]}, "R16B"}; -obsolete_1(snmpm, s, 5) -> - {removed, {snmpm, sync_set, [4,5]}, "R16B"}; -obsolete_1(snmpm, s, 6) -> - {removed, {snmpm, sync_set, [5,6]}, "R16B"}; -obsolete_1(snmpm, s, 7) -> - {removed, {snmpm, sync_set, 6}, "R16B"}; -obsolete_1(snmpm, as, 3) -> - {removed, {snmpm, async_set, 3}, "R16B"}; -obsolete_1(snmpm, as, 4) -> - {removed, {snmpm, async_set, [3,4]}, "R16B"}; -obsolete_1(snmpm, as, 5) -> - {removed, {snmpm, async_set, [4,5]}, "R16B"}; -obsolete_1(snmpm, as, 6) -> - {removed, {snmpm, async_set, [5,6]}, "R16B"}; -obsolete_1(snmpm, as, 7) -> - {removed, {snmpm, async_set, 6}, "R16B"}; -obsolete_1(snmpm, gb, 5) -> - {removed, {snmpm, sync_get_bulk, 5}, "R16B"}; -obsolete_1(snmpm, gb, 6) -> - {removed, {snmpm, sync_get_bulk, [5,6]}, "R16B"}; -obsolete_1(snmpm, gb, 7) -> - {removed, {snmpm, sync_get_bulk, [6,7]}, "R16B"}; -obsolete_1(snmpm, gb, 8) -> - {removed, {snmpm, sync_get_bulk, [7,8]}, "R16B"}; -obsolete_1(snmpm, gb, 9) -> - {removed, {snmpm, sync_get_bulk, 8}, "R16B"}; -obsolete_1(snmpm, agb, 5) -> - {removed, {snmpm, async_get_bulk, 5}, "R16B"}; -obsolete_1(snmpm, agb, 6) -> - {removed, {snmpm, async_get_bulk, [5,6]}, "R16B"}; -obsolete_1(snmpm, agb, 7) -> - {removed, {snmpm, async_get_bulk, [6,7]}, "R16B"}; -obsolete_1(snmpm, agb, 8) -> - {removed, {snmpm, async_get_bulk, [7,8]}, "R16B"}; -obsolete_1(snmpm, agb, 9) -> - {removed, {snmpm, async_get_bulk, 8}, "R16B"}; %% *** MEGACO *** @@ -431,64 +347,6 @@ obsolete_1(auth, node_cookie, 1) -> obsolete_1(auth, node_cookie, 2) -> {deprecated, "Deprecated; use erlang:set_cookie/2 and net_adm:ping/1 instead"}; -obsolete_1(http, request, 1) -> {removed,{httpc,request,1},"R15B"}; -obsolete_1(http, request, 2) -> {removed,{httpc,request,2},"R15B"}; -obsolete_1(http, request, 4) -> {removed,{httpc,request,4},"R15B"}; -obsolete_1(http, request, 5) -> {removed,{httpc,request,5},"R15B"}; -obsolete_1(http, cancel_request, 1) -> {removed,{httpc,cancel_request,1},"R15B"}; -obsolete_1(http, cancel_request, 2) -> {removed,{httpc,cancel_request,2},"R15B"}; -obsolete_1(http, set_option, 2) -> {removed,{httpc,set_option,2},"R15B"}; -obsolete_1(http, set_option, 3) -> {removed,{httpc,set_option,3},"R15B"}; -obsolete_1(http, set_options, 1) -> {removed,{httpc,set_options,1},"R15B"}; -obsolete_1(http, set_options, 2) -> {removed,{httpc,set_options,2},"R15B"}; -obsolete_1(http, verify_cookies, 2) -> {removed,{httpc,store_cookies,2},"R15B"}; -obsolete_1(http, verify_cookies, 3) -> {removed,{httpc,store_cookies,3},"R15B"}; -obsolete_1(http, cookie_header, 1) -> {removed,{httpc,cookie_header,1},"R15B"}; -obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"}; -obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"}; -obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"}; - -%% Added in R13A. -obsolete_1(regexp, _, _) -> - {removed, "removed in R15; use the re module instead"}; - -%% Added in R13B04. -obsolete_1(erlang, concat_binary, 1) -> - {removed,{erlang,list_to_binary,1},"R15B"}; - -%% Added in R14A. -obsolete_1(ssl, peercert, 2) -> - {removed ,"removed in R15A; use ssl:peercert/1 and public_key:pkix_decode_cert/2 instead"}; - -%% Added in R14B. -obsolete_1(public_key, pem_to_der, 1) -> - {removed,"removed in R15A; use file:read_file/1 and public_key:pem_decode/1"}; -obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 -> - {removed, "removed in R15A; use public_key:pem_entry_decode/1"}; - -%% Added in R14B03. -obsolete_1(docb_gen, _, _) -> - {removed,"the DocBuilder application was removed in R15B"}; -obsolete_1(docb_transform, _, _) -> - {removed,"the DocBuilder application was removed in R15B"}; -obsolete_1(docb_xml_check, _, _) -> - {removed,"the DocBuilder application was removed in R15B"}; - -%% Added in R15B -obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver -> - {removed,"removed (will be removed in OTP 18); has no effect as drivers are no longer used"}; -obsolete_1(ssl, pid, 1) -> - {removed,"was removed in R16; is no longer needed"}; -obsolete_1(inviso, _, _) -> - {removed,"the inviso application was removed in R16"}; - -%% Added in R15B01. -obsolete_1(ssh, sign_data, 2) -> - {removed,"removed in R16A; use public_key:pem_decode/1, public_key:pem_entry_decode/1 " - "and public_key:sign/3 instead"}; -obsolete_1(ssh, verify_data, 3) -> - {removed,"removed in R16A; use public_key:ssh_decode/1, and public_key:verify/4 instead"}; - %% Added in R16 obsolete_1(wxCalendarCtrl, enableYearChange, _) -> %% wx bug documented? {deprecated,"deprecated function not available in wxWidgets-2.9 and later"}; diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index e791da48cf..6d604794e7 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2109,11 +2109,10 @@ otp_5362(Config) when is_list(Config) -> {calendar,local_time_to_universal_time_dst,1}, "a future release"}}]}}, {call_removed_function, - <<"t(X) -> regexp:match(X).">>, + <<"t(X) -> erlang:hash(X, 10000).">>, [], {warnings, - [{1,erl_lint,{removed,{regexp,match,1}, - "removed in R15; use the re module instead"}}]}} + [{1,erl_lint,{removed,{erlang,hash,2},{erlang,phash2,2},"20.0"}}]}} ], -- cgit v1.2.3 From e92005be1bd88114de86dafb76c595248827241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 Apr 2019 05:47:57 +0200 Subject: No longer warn for use of the overload module The entire overload module was removed in OTP 19. Stopping warning for it now, since the module name could be used by code outside OTP. --- lib/stdlib/src/otp_internal.erl | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index f31356968e..25069a3db3 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -467,8 +467,6 @@ obsolete_1(queue, lait, 1) -> %% Removed in OTP 19. -obsolete_1(overload, _, _) -> - {removed, "removed in OTP 19"}; obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 -> {removed, {rpc, multi_server_call, A}, "removed in OTP 19"}; -- cgit v1.2.3 From 1c3e78ca91c081993cc32ba44d217ee8dda13368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 Apr 2019 07:09:35 +0200 Subject: Add a reminder to remove the warning for os_mon_mib in OTP 24 --- lib/stdlib/src/otp_internal.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 25069a3db3..a06da0511b 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -333,6 +333,7 @@ obsolete_1(megaco, format_versions, 1) -> %% *** OS-MON-MIB *** +%% FIXME: Remove this warning in OTP 24. obsolete_1(os_mon_mib, _, _) -> {removed, "was removed in 22.0"}; -- cgit v1.2.3 From 3d259fd70ed9e24e59746c5958730892e505f1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Fri, 5 Apr 2019 07:25:15 +0200 Subject: Correct description for removal of rpc:safe_multi_server_call/2 The warning would come out as: Warning: call to rpc:safe_multi_server_call/2 will fail, since it was removed in removed in OTP 19; use rpc:multi_server_call/2 ^^^^^^^^^^^^^^^^^^ --- lib/stdlib/src/otp_internal.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index a06da0511b..fa34f19637 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -469,7 +469,7 @@ obsolete_1(queue, lait, 1) -> %% Removed in OTP 19. obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 -> - {removed, {rpc, multi_server_call, A}, "removed in OTP 19"}; + {removed, {rpc, multi_server_call, A}, "19.0"}; %% Added in OTP 20. -- cgit v1.2.3 From 1a58a7c0a9af1eb98ddfecbc6157325f2c869eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Thu, 4 Apr 2019 06:09:31 +0200 Subject: Add options for suppressing warnings about removed functions An appliction outside of OTP may want to reuse then name of a module that was previously included in OTP. Therefore, there should be a way to suppress warnings for removed functions. --- lib/compiler/doc/src/compile.xml | 16 +++++++++++++ lib/edoc/src/edoc_data.erl | 2 ++ lib/stdlib/src/erl_lint.erl | 46 +++++++++++++++++++++++++++++++++----- lib/stdlib/test/erl_lint_SUITE.erl | 24 +++++++++++++++++++- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index 5219ba0f5d..549b1049d8 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -632,6 +632,22 @@ module.beam: module.erl \ to be deprecated.

+ nowarn_removed + +

Turns off warnings for calls to functions that have + been removed. Default is to emit warnings for every call + to a function known by the compiler to have been recently + removed from Erlang/OTP.

+
+ + {nowarn_removed, ModulesOrMFAs} + +

Turns off warnings for calls to modules or functions + that have been removed. Default is to emit warnings for + every call to a function known by the compiler to have + been recently removed from Erlang/OTP.

+
+ nowarn_obsolete_guard

Turns off warnings for calls to old type testing BIFs, diff --git a/lib/edoc/src/edoc_data.erl b/lib/edoc/src/edoc_data.erl index 7c077d3acd..a8373d6536 100644 --- a/lib/edoc/src/edoc_data.erl +++ b/lib/edoc/src/edoc_data.erl @@ -345,6 +345,8 @@ deprecated(Repl, Env) -> deprecated(Desc) -> [{deprecated, description(Desc)}]. +-dialyzer({no_match, replacement_function/2}). + replacement_function(M0, {M,F,A}) when is_list(A) -> %% refer to the largest listed arity - the most general version replacement_function(M0, {M,F,lists:last(lists:sort(A))}); diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 3ec78a2667..00fd731e1d 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -79,6 +79,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> -type fa() :: {atom(), arity()}. % function+arity -type ta() :: {atom(), arity()}. % type+arity +-type module_or_mfa() :: module() | mfa(). + -record(typeinfo, {attr, line}). %% Usage of records, functions, and imports. The variable table, which @@ -115,6 +117,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> :: erl_anno:anno(), clashes=[], %Exported functions named as BIFs not_deprecated=[], %Not considered deprecated + not_removed=gb_sets:empty() %Not considered removed + :: gb_sets:set(module_or_mfa()), func=[], %Current function warn_format=0, %Warn format calls enabled_warnings=[], %All enabled warnings (ordset). @@ -573,7 +577,10 @@ start(File, Opts) -> false, Opts)}, {missing_spec_all, bool_option(warn_missing_spec_all, nowarn_missing_spec_all, - false, Opts)} + false, Opts)}, + {removed, + bool_option(warn_removed, nowarn_removed, + true, Opts)} ], Enabled1 = [Category || {Category,true} <- Enabled0], Enabled = ordsets:from_list(Enabled1), @@ -670,8 +677,9 @@ forms(Forms0, St0) -> no_auto = AutoImportSuppressed}), St2 = bif_clashes(Forms, St1), St3 = not_deprecated(Forms, St2), - St4 = foldl(fun form/2, pre_scan(Forms, St3), Forms), - post_traversal_check(Forms, St4). + St4 = not_removed(Forms, St3), + St5 = foldl(fun form/2, pre_scan(Forms, St4), Forms), + post_traversal_check(Forms, St5). pre_scan([{attribute,L,compile,C} | Fs], St) -> case is_warn_enabled(export_all, St) andalso @@ -846,6 +854,24 @@ not_deprecated(Forms, #lint{compile=Opts}=St0) -> end, St0, ML), St1#lint{not_deprecated = ordsets:from_list(Nowarn)}. +%% not_removed(Forms, State0) -> State + +not_removed(Forms, #lint{compile=Opts}=St0) -> + %% There are no line numbers in St0#lint.compile. + MFAsL = [{MFA,L} || + {attribute, L, compile, Args} <- Forms, + {nowarn_removed, MFAs0} <- lists:flatten([Args]), + MFA <- lists:flatten([MFAs0])], + Nowarn = [MFA || + {nowarn_removed, MFAs0} <- Opts, + MFA <- lists:flatten([MFAs0])], + St1 = foldl(fun ({{M, _F, _A}, L}, St2) -> + check_module_name(M, L, St2); + ({M,L}, St2) -> + check_module_name(M, L, St2) + end, St0, MFAsL), + St1#lint{not_removed = gb_sets:from_list(Nowarn)}. + %% The nowarn_bif_clash directive is not only deprecated, it's actually an error from R14A disallowed_compile_flags(Forms, St0) -> %% There are (still) no line numbers in St0#lint.compile. @@ -3769,13 +3795,23 @@ deprecated_function(Line, M, F, As, St) -> add_warning(Line, {deprecated, MFA, Replacement, Rel}, St) end; {removed, String} when is_list(String) -> - add_warning(Line, {removed, MFA, String}, St); + add_removed_warning(Line, MFA, {removed, MFA, String}, St); {removed, Replacement, Rel} -> - add_warning(Line, {removed, MFA, Replacement, Rel}, St); + add_removed_warning(Line, MFA, {removed, MFA, Replacement, Rel}, St); no -> St end. +add_removed_warning(Line, {M, _, _}=MFA, Warning, #lint{not_removed=NotRemoved}=St) -> + case is_warn_enabled(removed, St) andalso + not gb_sets:is_element(M, NotRemoved) andalso + not gb_sets:is_element(MFA, NotRemoved) of + true -> + add_warning(Line, Warning, St); + false -> + St + end. + -dialyzer({no_match, deprecated_type/5}). deprecated_type(L, M, N, As, St) -> diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 6d604794e7..939cc1024c 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2112,7 +2112,29 @@ otp_5362(Config) when is_list(Config) -> <<"t(X) -> erlang:hash(X, 10000).">>, [], {warnings, - [{1,erl_lint,{removed,{erlang,hash,2},{erlang,phash2,2},"20.0"}}]}} + [{1,erl_lint,{removed,{erlang,hash,2},{erlang,phash2,2},"20.0"}}]}}, + + {nowarn_call_removed_function_1, + <<"t(X) -> erlang:hash(X, 10000).">>, + [{nowarn_removed,{erlang,hash,2}}], + []}, + + {nowarn_call_removed_function_2, + <<"t(X) -> os_mon_mib:any_function_really(erlang:hash(X, 10000)).">>, + [nowarn_removed], + []}, + + {call_removed_module, + <<"t(X) -> os_mon_mib:any_function_really(X).">>, + [], + {warnings,[{1,erl_lint, + {removed,{os_mon_mib,any_function_really,1}, + "was removed in 22.0"}}]}}, + + {nowarn_call_removed_module, + <<"t(X) -> os_mon_mib:any_function_really(X).">>, + [{nowarn_removed,os_mon_mib}], + []} ], -- cgit v1.2.3