aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-04-19 15:02:17 +0200
committerHans Bolinder <[email protected]>2016-04-28 16:16:10 +0200
commit29253c06dd99717e8424c0418144fd95d232c38d (patch)
treeff4f7a891ba26d05a8479936a073610cbf8cb760
parentd2ba8674603bc4ef210ec91e6f51924f7efe8c2e (diff)
downloadotp-29253c06dd99717e8424c0418144fd95d232c38d.tar.gz
otp-29253c06dd99717e8424c0418144fd95d232c38d.tar.bz2
otp-29253c06dd99717e8424c0418144fd95d232c38d.zip
erl_types: Fix t_subtract/2 correctness bug
t_subtract/2 would break its postcondition by always returning the underapproximation none() when given a variable on the right hand side. This broke map type parsing, since it relied on t_subtract/2 to tell it when map keys would shadow each other.
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/opaque_key4
-rw-r--r--lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl10
-rw-r--r--lib/hipe/cerl/erl_types.erl2
3 files changed, 7 insertions, 9 deletions
diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
index df8c825b18..d663e7d217 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key
+++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key
@@ -1,8 +1,6 @@
-opaque_key_adt.erl:32: Invalid type specification for function opaque_key_adt:s1/0. The success typing is () -> #{3:='a'}
-opaque_key_adt.erl:35: Invalid type specification for function opaque_key_adt:s2/0. The success typing is () -> #{3:='a'}
opaque_key_adt.erl:41: Invalid type specification for function opaque_key_adt:s4/0. The success typing is () -> #{1:='a'}
-opaque_key_adt.erl:53: Invalid type specification for function opaque_key_adt:sm1/0. The success typing is () -> #{1:=2, 3:='a'}
+opaque_key_adt.erl:44: Invalid type specification for function opaque_key_adt:s5/0. The success typing is () -> #{2:=3}
opaque_key_adt.erl:56: Invalid type specification for function opaque_key_adt:smt1/0. The success typing is () -> #{3:='a'}
opaque_key_adt.erl:59: Invalid type specification for function opaque_key_adt:smt2/0. The success typing is () -> #{1:='a'}
opaque_key_use.erl:13: The test opaque_key_use:t() =:= opaque_key_use:t(integer()) can never evaluate to 'true'
diff --git a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
index 53ec09b062..b98c713c6b 100644
--- a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
+++ b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl
@@ -29,20 +29,20 @@ mt0() -> #{#{} => 3}.
-spec s0() -> s(atom()).
s0() -> #{}.
--spec s1() -> s(atom()). %% No contract breakage (bad warning)
+-spec s1() -> s(atom()).
s1() -> #{3 => a}.
-spec s2() -> s(atom() | 3).
-s2() -> #{3 => a}. %% Contract breakage
+s2() -> #{3 => a}. %% Contract breakage (not found)
-spec s3() -> s(atom() | 3).
s3() -> #{3 => 5, a => 6, 7 => 8}.
-spec s4() -> s(integer()).
-s4() -> #{1 => a}. %% Actual contract breakage (good warning)
+s4() -> #{1 => a}. %% Contract breakage
-spec s5() -> s(1).
-s5() -> #{2 => 3}. %% Contract breakage (not found)
+s5() -> #{2 => 3}. %% Contract breakage
-spec s6() -> s(1).
s6() -> #{1 => 3}.
@@ -50,7 +50,7 @@ s6() -> #{1 => 3}.
-spec s7() -> s(integer()).
s7() -> #{1 => 3}.
--spec sm1() -> sm(1). %% No contract breakage (bad warning)
+-spec sm1() -> sm(1).
sm1() -> #{1 => 2, 3 => a}.
-spec smt1() -> smt(1).
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index 8057e37d0c..1f0bc7eda1 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -3694,7 +3694,7 @@ t_subtract_list(T, []) ->
-spec t_subtract(erl_type(), erl_type()) -> erl_type().
t_subtract(_, ?any) -> ?none;
-t_subtract(_, ?var(_)) -> ?none;
+t_subtract(T, ?var(_)) -> T;
t_subtract(?any, _) -> ?any;
t_subtract(?var(_) = T, _) -> T;
t_subtract(T, ?unit) -> T;