diff options
| -rw-r--r-- | lib/dialyzer/src/dialyzer_contracts.erl | 4 | ||||
| -rw-r--r-- | lib/dialyzer/test/small_SUITE_data/results/chars | 6 | ||||
| -rw-r--r-- | lib/dialyzer/test/small_SUITE_data/results/extra_range | 4 | ||||
| -rw-r--r-- | lib/dialyzer/test/small_SUITE_data/src/chars.erl | 18 | ||||
| -rw-r--r-- | lib/dialyzer/test/small_SUITE_data/src/extra_range.erl | 59 | 
5 files changed, 83 insertions, 8 deletions
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl index e72c1aecfc..0df15e55f9 100644 --- a/lib/dialyzer/src/dialyzer_contracts.erl +++ b/lib/dialyzer/src/dialyzer_contracts.erl @@ -197,6 +197,10 @@ check_contracts(Contracts, Callgraph, FunTypes, ModOpaques) ->  		      false ->  			[{MFA, Contract}|NewContracts]  		    end; +                  {error, {extra_range, _, _}} -> +                    %% do not treat extra range as an error in this check +                    %% since that prevents discovering other actual errors +                    [{MFA, Contract}|NewContracts];  		  {error, _Error} -> NewContracts  		end;  	      error -> NewContracts diff --git a/lib/dialyzer/test/small_SUITE_data/results/chars b/lib/dialyzer/test/small_SUITE_data/results/chars index 2c1f8f8d17..72fbdb4528 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/chars +++ b/lib/dialyzer/test/small_SUITE_data/results/chars @@ -1,4 +1,4 @@ -chars.erl:29: Invalid type specification for function chars:f/1. The success typing is (#{'b':=50}) -> 'ok' -chars.erl:32: Function t1/0 has no local return -chars.erl:32: The call chars:f(#{'b':=50}) breaks the contract (#{'a':=49,'b'=>50,'c'=>51}) -> 'ok' +chars.erl:37: Invalid type specification for function chars:f/1. The success typing is (#{'b':=50}) -> 'ok' +chars.erl:40: Function t1/0 has no local return +chars.erl:40: The call chars:f(#{'b':=50}) breaks the contract (#{'a':=49,'b'=>50,'c'=>51}) -> 'ok' diff --git a/lib/dialyzer/test/small_SUITE_data/results/extra_range b/lib/dialyzer/test/small_SUITE_data/results/extra_range new file mode 100644 index 0000000000..ec50c95c4e --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/extra_range @@ -0,0 +1,4 @@ + +extra_range.erl:29: The pattern 'ok' can never match the type 'error' +extra_range.erl:43: The pattern 'no' can never match the type 'maybe' | 'yes' +extra_range.erl:58: The pattern 'maybe' can never match the type 'no' | 'yes' diff --git a/lib/dialyzer/test/small_SUITE_data/src/chars.erl b/lib/dialyzer/test/small_SUITE_data/src/chars.erl index 1e9c8ab6b9..62b90cf54d 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/chars.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/chars.erl @@ -12,17 +12,25 @@  -spec t() -> $0-$0..$9-$0| $?.  t() -> -    c(#r{f = $z - 3}), +    r(#r{f = $z - 3}), +    r(#r{f = 97}), +    c($/),      c($z - 3),      c($B).  -spec c(cs()) -> $3-$0..$9-$0. - -c($A + 1) -> 2; +c($A + 1) -> $9-$0;  c(C) ->      case C of -        $z - 3 -> 3; -        #r{f = $z - 3} -> 7 +        $z - 3 -> $3-$0; +        _ -> $7-$0 +    end. + +-spec r(#r{f :: $a..$z}) -> ok | error. +r(R) -> +    case R of +        #r{f = $z - 3} -> error; +        _ -> ok      end.  %% Display contract with character in warning: diff --git a/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl new file mode 100644 index 0000000000..9d6ba89c95 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/extra_range.erl @@ -0,0 +1,59 @@ +%% Test that a spec containing more items than actually returned +%% (whether by accident or by benign overspeccing) does not prevent +%% detection of impossible matches. + +-module(extra_range). + +-export([t1/2, t2/2, t3/2, t4/2]). + +-dialyzer([no_return]). + +%% this spec matches the behaviour of the code +-spec normal(integer()) -> ok | error. +normal(1) -> ok; +normal(2) -> error. + +t1(X, Y) when is_integer(X), is_integer(Y) -> +    ok = normal(X), +    error = normal(Y), +    ok. + + +%% this spec has a typo, which should cause anyone trying to match on +%% `ok = typo(X)' to get a warning, because `ok' is not in the spec +-spec typo(integer()) -> ook | error. +typo(1) -> ok; +typo(2) -> error. + +t2(X, Y) when is_integer(X), is_integer(Y) -> +    ok = typo(X),  % warning expected - not allowed according to spec +    error = typo(Y), +    ok. + + +%% this is overspecified, and should cause a warning for trying +%% to match on `no = over(X)', because it cannot succeed and either +%% the spec should be updated or the code should be extended +-spec over(integer()) -> yes | no | maybe. +over(1) -> yes; +over(_) -> maybe. + +t3(X, Y) when is_integer(X), is_integer(Y) -> +    yes = over(X), +    no = over(Y),  % warning expected - spec or code needs fixing +    maybe = over(X + Y), +    ok. + + +%% this is underspecified, which should cause anyone trying to match on +%% `maybe = under(X)' to get a warning, because `maybe' is not in the spec +-spec under(integer()) -> yes | no. +under(1) -> yes; +under(2) -> no; +under(_) -> maybe. + +t4(X, Y) when is_integer(X), is_integer(Y) -> +    yes = under(X), +    no = under(Y), +    maybe = under(X + Y), % warning expected - not in spec +    ok.  | 
