Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:19
erlang
0817-dialyzer-Fix-an-overloaded-contract-warnin...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0817-dialyzer-Fix-an-overloaded-contract-warning.patch of Package erlang
From e25ed9ca25cae5dccb44f0f2204eb795c31c291e Mon Sep 17 00:00:00 2001 From: Hans Bolinder <hasse@erlang.org> Date: Tue, 12 Nov 2019 16:10:43 +0100 Subject: [PATCH 1/2] dialyzer: Fix an overloaded contract warning When creating the missing_range warning, the supremum of all function type ranges is considered, not the range of one function type at a time. Notice that more extra_range messages than before can be emitted (the check for extra_range was not always performed if a missing_range was found). --- lib/dialyzer/src/dialyzer_contracts.erl | 36 +++++++++++---------- .../test/specdiffs_SUITE_data/results/overloaded | 6 ++++ .../test/specdiffs_SUITE_data/src/overloaded.erl | 37 ++++++++++++++++++++++ 3 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 lib/dialyzer/test/specdiffs_SUITE_data/results/overloaded create mode 100644 lib/dialyzer/test/specdiffs_SUITE_data/src/overloaded.erl diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index 17b2168852..e041c43cc1 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -248,7 +248,19 @@ check_contract(#contract{contracts = Contracts}, SuccType, Opaques) -> || Contract <- Contracts2], case check_contract_inf_list(InfList, SuccType, Opaques) of {error, _} = Invalid -> Invalid; - ok -> check_extraneous(Contracts2, SuccType) + ok -> + case check_extraneous(Contracts2, SuccType) of + {error, invalid_contract} = Err -> + Err; + {error, {extra_range, _, _}} = Err -> + MissingError = check_missing(Contracts2, SuccType), + {range_warnings, [Err | MissingError]}; + ok -> + case check_missing(Contracts2, SuccType) of + [] -> ok; + ErrorL -> {range_warnings, ErrorL} + end + end end end catch @@ -304,15 +316,8 @@ check_contract_inf_list([], _SuccType, _Opaques, OM) -> check_extraneous([], _SuccType) -> ok; check_extraneous([C|Cs], SuccType) -> case check_extraneous_1(C, SuccType) of - {error, invalid_contract} = Error -> - Error; - {error, {extra_range, _, _}} = Error -> - {range_warnings, [Error | check_missing(C, SuccType)]}; - ok -> - case check_missing(C, SuccType) of - [] -> check_extraneous(Cs, SuccType); - ErrorL -> {range_warnings, ErrorL} - end + {error, _} = Error -> Error; + ok -> check_extraneous(Cs, SuccType) end. check_extraneous_1(Contract, SuccType) -> @@ -363,16 +368,15 @@ map_part(Type) -> is_empty_map(Type) -> erl_types:t_is_equal(Type, erl_types:t_from_term(#{})). -check_missing(Contract, SuccType) -> - CRng = erl_types:t_fun_range(Contract), +check_missing(Contracts, SuccType) -> + CRanges = [erl_types:t_fun_range(C) || C <- Contracts], + AllCRange = erl_types:t_sup(CRanges), STRng = erl_types:t_fun_range(SuccType), STRngs = erl_types:t_elements(STRng), - ?debug("\nCR = ~ts\nSR = ~ts\n", [erl_types:t_to_string(CRng), - erl_types:t_to_string(STRng)]), case [STR || STR <- STRngs, - erl_types:t_is_none(erl_types:t_inf(STR, CRng))] of + erl_types:t_is_none(erl_types:t_inf(STR, AllCRange))] of [] -> []; - STRs -> [{error, {missing_range, erl_types:t_sup(STRs), CRng}}] + STRs -> [{error, {missing_range, erl_types:t_sup(STRs), AllCRange}}] end. %% This is the heart of the "range function" diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/results/overloaded b/lib/dialyzer/test/specdiffs_SUITE_data/results/overloaded new file mode 100644 index 0000000000..f68917c009 --- /dev/null +++ b/lib/dialyzer/test/specdiffs_SUITE_data/results/overloaded @@ -0,0 +1,6 @@ + +overloaded.erl:12: Type specification overloaded:u('a' | 'b' | 'c') -> term() is a subtype of the success typing: overloaded:u(_) -> any() +overloaded.erl:17: The success typing for overloaded:v/1 implies that the function might also return {'ok','term'} but the specification return is 'ok' +overloaded.erl:22: Type specification overloaded:x(_) -> {'ok','term'} | 'ok' is a supertype of the success typing: overloaded:x('a' | 'b') -> 'ok' | {'ok','term'} +overloaded.erl:29: The success typing for overloaded:over/1 implies that the function might also return 'ffyy3' but the specification return is 'ffyy1' | {'ffyy2',integer()} +overloaded.erl:7: Type specification overloaded:t('a' | 'b') -> term() is a subtype of the success typing: overloaded:t('a' | 'b' | 'c') -> any() diff --git a/lib/dialyzer/test/specdiffs_SUITE_data/src/overloaded.erl b/lib/dialyzer/test/specdiffs_SUITE_data/src/overloaded.erl new file mode 100644 index 0000000000..67757fbb2a --- /dev/null +++ b/lib/dialyzer/test/specdiffs_SUITE_data/src/overloaded.erl @@ -0,0 +1,37 @@ +-module(overloaded). + +-export([t/1, v/1]). + +-export([over/1]). + +-spec t(a | b) -> term(). + +t(A) -> + u(A). + +-spec u(a | b | c) -> term(). + +u(X) -> + X. + +-spec v(_) -> ok. + +v(A) -> + x(A). + +-spec x(_) -> {ok, term} | ok. + +x(a) -> + {ok, term}; +x(b) -> + ok. + +-spec over(A) -> ffyy1 when A :: a | b; + (B) -> {ffyy2, integer()} when B :: c | d. + +over(a) -> + ffyy1; +over(c) -> + {ffyy2, 1}; +over(d) -> + ffyy3. -- 2.16.4
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