aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2011-09-18 15:26:24 +0200
committerBjörn Gustavsson <[email protected]>2011-09-21 11:09:19 +0200
commit4e3be15240c8d3f2897a994e8399684d5c8b6268 (patch)
tree9df251795babce87220504af42a7c0b389eb907e
parent2d6bb0b74427e29b9333bba57683472181243ba5 (diff)
downloadotp-4e3be15240c8d3f2897a994e8399684d5c8b6268.tar.gz
otp-4e3be15240c8d3f2897a994e8399684d5c8b6268.tar.bz2
otp-4e3be15240c8d3f2897a994e8399684d5c8b6268.zip
erl_bif_types: Fix types for lists:key{search,find,member}/3
The types for lists:key{search,find,member}/3 was computed under the assumption that the key should be matched (=:=) to the keys in the list, while the actual implementation uses comparison (==). Thus erl_bif_types:types/4 would wrongly report that lists:keyfind(42, 1, [{42.0,a}]) would always return 'false'.
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl26
1 files changed, 12 insertions, 14 deletions
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 827fa79ec5..4163f2dae2 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2329,10 +2329,7 @@ type(lists, keyfind, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2362,9 +2359,7 @@ type(lists, keymember, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> t_boolean();
List ->
- Keys = [type(erlang, element, 2, [Y,S]) || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> t_boolean()
end
@@ -2394,10 +2389,7 @@ type(lists, keysearch, 3, Xs) ->
case t_tuple_subtypes(Tuple) of
unknown -> Ret;
List ->
- Keys = [type(erlang, element, 2, [Y, S])
- || S <- List],
- Infs = [t_inf(Key, X) || Key <- Keys],
- case all_is_none(Infs) of
+ case key_comparisons_fail(X, Y, List) of
true -> t_atom('false');
false -> Ret
end
@@ -2825,9 +2817,6 @@ list_replace(1, E, [_X | Xs]) ->
any_is_none_or_unit(Ts) ->
lists:any(fun erl_types:t_is_none_or_unit/1, Ts).
-all_is_none(Ts) ->
- lists:all(fun erl_types:t_is_none/1, Ts).
-
check_guard([X], Test, Type) ->
check_guard_single(X, Test, Type).
@@ -3222,6 +3211,15 @@ type_order() ->
[t_number(), t_atom(), t_reference(), t_fun(), t_port(), t_pid(), t_tuple(),
t_list(), t_binary()].
+key_comparisons_fail(X0, KeyPos, TupleList) ->
+ X = case t_is_number(t_inf(X0, t_number())) of
+ false -> X0;
+ true -> t_number()
+ end,
+ lists:all(fun(Tuple) ->
+ Key = type(erlang, element, 2, [KeyPos, Tuple]),
+ t_is_none(t_inf(Key, X))
+ end, TupleList).
%%=============================================================================