LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0151-Dialyzer-should-not-throw-away-spec-information-beca.patch of Package erlang (Project home:Ledest:erlang:20)

From 9883f9714bd4a56ae9d68b3b0e7958461918946e Mon Sep 17 00:00:00 2001
From: Richard Carlsson <carlsson.richard@gmail.com>
Date: Tue, 20 Feb 2018 13:47:25 +0100
Subject: [PATCH 1/4] Dialyzer should not throw away spec information because
 of overspec

---
 lib/dialyzer/src/dialyzer_contracts.erl            |  4 ++
 lib/dialyzer/test/small_SUITE_data/results/chars   |  6 +--
 .../test/small_SUITE_data/results/extra_range      |  4 ++
 lib/dialyzer/test/small_SUITE_data/src/chars.erl   | 18 +++++--
 .../test/small_SUITE_data/src/extra_range.erl      | 59 ++++++++++++++++++++++
 5 files changed, 83 insertions(+), 8 deletions(-)
 create mode 100644 lib/dialyzer/test/small_SUITE_data/results/extra_range
 create mode 100644 lib/dialyzer/test/small_SUITE_data/src/extra_range.erl

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.
-- 
2.16.2