From f0ec1835897a017ec7d7613add1870850187b7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Tue, 19 Apr 2016 16:43:19 +0200 Subject: erl_types: Don't consider opaque keys singleton Opaque singleton keys have the unfortunate property, unlike any other singleton type, to overlap with other singleton types that do not have the same internal representation. Therefore, we must not keep opaque singletons in the Pairs list in a map type. --- lib/dialyzer/test/map_SUITE_data/results/opaque_key | 4 ---- lib/hipe/cerl/erl_types.erl | 17 +++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key index d663e7d217..fb7080cdc5 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key +++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key @@ -5,7 +5,6 @@ opaque_key_adt.erl:56: Invalid type specification for function opaque_key_adt:sm 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' opaque_key_use.erl:24: Attempt to test for equality between a term of type opaque_key_adt:t(integer()) and a term of opaque type opaque_key_adt:t() -opaque_key_use.erl:26: Function adt_tt2/0 has no local return opaque_key_use.erl:37: Function adt_mm1/0 has no local return opaque_key_use.erl:40: The attempt to match a term of type opaque_key_adt:m() against the pattern #{A:=R} breaks the opaqueness of the term opaque_key_use.erl:48: Function adt_mu1/0 has no local return @@ -14,6 +13,3 @@ opaque_key_use.erl:53: Function adt_mu2/0 has no local return opaque_key_use.erl:56: Guard test is_map(M::opaque_key_adt:m()) breaks the opaqueness of its argument opaque_key_use.erl:58: Function adt_mu3/0 has no local return opaque_key_use.erl:60: Guard test is_map(M::opaque_key_adt:m()) breaks the opaqueness of its argument -opaque_key_use.erl:62: Function adt_mtm1/0 has no local return -opaque_key_use.erl:73: Function adt_mtu1/0 has no local return -opaque_key_use.erl:78: Function adt_mtu2/0 has no local return diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 1f0bc7eda1..58060361af 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -1651,7 +1651,7 @@ t_map(Pairs0, DefK0, DefV0) -> false -> {DefK1, DefV0} end, {Pairs1, DefK, DefV} - = case t_is_singleton(DefK2) of + = case is_singleton_type(DefK2) of true -> {mapdict_insert({DefK2, ?opt, DefV1}, Pairs0), ?none, ?none}; false -> {Pairs0, DefK2, DefV1} end, @@ -1684,12 +1684,12 @@ normalise_map_optionals([E|T], DefK, DefV) -> validate_map_elements([{_,?mand,?none}|_]) -> error({badarg, none_in_mand}); validate_map_elements([{K1,_,_}|Rest=[{K2,_,_}|_]]) -> - case t_is_singleton(K1) andalso K1 < K2 of + case is_singleton_type(K1) andalso K1 < K2 of false -> error(badarg); true -> validate_map_elements(Rest) end; validate_map_elements([{K,_,_}]) -> - case t_is_singleton(K) of + case is_singleton_type(K) of false -> error(badarg); true -> true end; @@ -1841,7 +1841,7 @@ map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) -> case t_is_none_or_unit(Key) orelse t_is_none_or_unit(Value) of true -> ?none; false -> - case t_is_singleton(Key) of + case is_singleton_type(Key) of true -> t_map(mapdict_store({Key, ?mand, Value}, Pairs), DefK, DefV); false -> @@ -1888,7 +1888,7 @@ map_get(Key, ?map(Pairs, DefK, DefV)) -> false -> t_none(); true -> DefV end, - case t_is_singleton(Key) of + case is_singleton_type(Key) of false -> lists:foldl(fun({K, _, V}, Res) -> case t_do_overlap(K, Key) of @@ -1918,7 +1918,7 @@ t_map_is_key(Key, Map, Opaques) -> map_is_key(_, ?none) -> ?none; map_is_key(Key, ?map(Pairs, DefK, _DefV)) -> - case t_is_singleton(Key) of + case is_singleton_type(Key) of true -> case lists:keyfind(Key, 1, Pairs) of {Key, ?mand, _} -> t_atom(true); @@ -2275,7 +2275,8 @@ t_from_term(T) when is_integer(T) -> t_integer(T); t_from_term(T) when is_map(T) -> Pairs = [{t_from_term(K), ?mand, t_from_term(V)} || {K, V} <- maps:to_list(T)], - {Stons, Rest} = lists:partition(fun({K,_,_}) -> t_is_singleton(K) end, Pairs), + {Stons, Rest} = lists:partition(fun({K,_,_}) -> is_singleton_type(K) end, + Pairs), {DefK, DefV} = lists:foldl(fun({K,_,V},{AK,AV}) -> {t_sup(K,AK), t_sup(V,AV)} end, {t_none(), t_none()}, Rest), @@ -4987,7 +4988,7 @@ map_from_form([{SKey,MNess,Val}|SPairs], ShdwPs0, MKs0, Pairs0, DefK0, DefV0) -> true -> ok end, {Pairs, DefK, DefV} = - case t_is_singleton(Key) of + case is_singleton_type(Key) of true -> MNess1 = case Val =:= ?none of true -> ?opt; false -> MNess end, {mapdict_insert({Key,MNess1,Val}, Pairs0), DefK0, DefV0}; -- cgit v1.2.3