File 0770-dialyzer-Handle-maps-remove-2-better.patch of Package erlang
From 212a5ef0e2a0b38be365c098ddb4c8b9c5a1cd22 Mon Sep 17 00:00:00 2001
From: Hans Bolinder <hasse@erlang.org>
Date: Mon, 9 Sep 2019 15:46:48 +0200
Subject: [PATCH] dialyzer: Handle maps:remove/2 better
See also ERL-1002.
---
.../test/map_SUITE_data/results/maps_remove | 4 ++++
.../test/map_SUITE_data/src/maps_remove.erl | 23 ++++++++++++++++++++++
lib/hipe/cerl/erl_bif_types.erl | 8 ++++++++
lib/hipe/cerl/erl_types.erl | 22 +++++++++++++++++++++
lib/stdlib/src/maps.erl | 3 ++-
5 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 lib/dialyzer/test/map_SUITE_data/results/maps_remove
create mode 100644 lib/dialyzer/test/map_SUITE_data/src/maps_remove.erl
diff --git a/lib/dialyzer/test/map_SUITE_data/results/maps_remove b/lib/dialyzer/test/map_SUITE_data/results/maps_remove
new file mode 100644
index 0000000000..32e43466b0
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/results/maps_remove
@@ -0,0 +1,4 @@
+
+maps_remove.erl:22: Function get/2 has no local return
+maps_remove.erl:23: The call maps:get(K::'a',M::#{}) will never return since the success typing arguments are (any(),map())
+maps_remove.erl:7: Function t1/0 has no local return
diff --git a/lib/dialyzer/test/map_SUITE_data/src/maps_remove.erl b/lib/dialyzer/test/map_SUITE_data/src/maps_remove.erl
new file mode 100644
index 0000000000..b913e389f8
--- /dev/null
+++ b/lib/dialyzer/test/map_SUITE_data/src/maps_remove.erl
@@ -0,0 +1,23 @@
+%% ERL-1002, maps:remove
+
+-module(maps_remove).
+
+-export([t1/0]).
+
+t1() ->
+ A = new(),
+ B = put(a, 1, A),
+ C = remove(a, B),
+ get(a, C).
+
+new() ->
+ maps:new().
+
+put(K, V, M) ->
+ maps:put(K, V, M).
+
+remove(K, M) ->
+ maps:remove(K, M).
+
+get(K, M) ->
+ maps:get(K, M).
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 8ae1cd4ab7..ded93211fa 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -115,6 +115,7 @@
t_map_is_key/3,
t_map_entries/2,
t_map_put/3,
+ t_map_remove/3,
t_map_update/3,
t_map_pairwise_merge/4
]).
@@ -1691,6 +1692,11 @@ type(maps, put, 3, Xs, Opaques) ->
fun ([Key, Value, Map]) ->
t_map_put({Key, Value}, Map, Opaques)
end, Opaques);
+type(maps, remove, 2, Xs, Opaques) ->
+ strict(maps, remove, 2, Xs,
+ fun ([Key, Map]) ->
+ t_map_remove(Key, Map, Opaques)
+ end, Opaques);
type(maps, size, 1, Xs, Opaques) ->
strict(maps, size, 1, Xs,
fun ([Map]) ->
@@ -2652,6 +2658,8 @@ arg_types(maps, merge, 2) ->
[t_map(), t_map()];
arg_types(maps, put, 3) ->
[t_any(), t_any(), t_map()];
+arg_types(maps, remove, 2) ->
+ [t_any(), t_map()];
arg_types(maps, size, 1) ->
[t_map()];
arg_types(maps, to_list, 1) ->
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index badf58936f..5f5612fcd3 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -154,6 +154,7 @@
t_map_update/2, t_map_update/3,
t_map_pairwise_merge/4,
t_map_put/2, t_map_put/3,
+ t_map_remove/3,
t_matchstate/0,
t_matchstate/2,
t_matchstate_present/1,
@@ -1925,6 +1926,27 @@ map_put({Key, Value}, ?map(Pairs,DefK,DefV), Opaques) ->
end
end.
+-spec t_map_remove(erl_type(), erl_type(), opaques()) -> erl_type().
+
+t_map_remove(Key, Map, Opaques) ->
+ do_opaque(Map, Opaques, fun(UM) -> map_remove(Key, UM) end).
+
+map_remove(_, ?none) -> ?none;
+map_remove(_, ?unit) -> ?none;
+map_remove(Key, Map) ->
+ %% ?map(lists:keydelete(Key, 1, Pairs), DefK, DefV).
+ case is_singleton_type(Key) of
+ false -> Map;
+ true ->
+ ?map(Pairs,DefK,DefV) = Map,
+ case lists:keyfind(Key, 1, Pairs) of
+ false -> Map;
+ {Key, _, _} ->
+ Pairs1 = lists:keydelete(Key, 1, Pairs),
+ t_map(Pairs1, DefK, DefV)
+ end
+ end.
+
-spec t_map_update({erl_type(), erl_type()}, erl_type()) -> erl_type().
t_map_update(KV, Map) ->
diff --git a/lib/stdlib/src/maps.erl b/lib/stdlib/src/maps.erl
index 51965ddb57..49d6a12eb2 100644
--- a/lib/stdlib/src/maps.erl
+++ b/lib/stdlib/src/maps.erl
@@ -95,6 +95,7 @@ merge(_,_) -> erlang:nif_error(undef).
put(_,_,_) -> erlang:nif_error(undef).
+%% Shadowed by erl_bif_types: maps:remove/2
-spec remove(Key,Map1) -> Map2 when
Key :: term(),
Map1 :: map(),
--
2.16.4