101 lines
3.8 KiB
Diff
101 lines
3.8 KiB
Diff
From 7715f437ab9a789e0500873b6002a49bfe69009c Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
|
|
Date: Fri, 29 Sep 2017 07:17:01 +0200
|
|
Subject: [PATCH] Fix incorrect internal consistency failure for binary
|
|
matching code
|
|
|
|
4c31fd0b9665 made the merging of match contexts stricter;
|
|
in fact, a little bit too strict.
|
|
|
|
Two match contexts with different number of slots would
|
|
be downgraded to the 'term' type. The correct way is to
|
|
keep the match context but set the number of slots to the
|
|
lowest number of slots of the two match contexts.
|
|
|
|
https://bugs.erlang.org/browse/ERL-490
|
|
---
|
|
lib/compiler/src/beam_validator.erl | 6 +++---
|
|
lib/compiler/test/bs_match_SUITE.erl | 38 ++++++++++++++++++++++++++++++++++--
|
|
2 files changed, 39 insertions(+), 5 deletions(-)
|
|
|
|
--- otp_src_20.1/lib/compiler/src/beam_validator.erl
|
|
+++ otp_src_20.1/lib/compiler/src/beam_validator.erl
|
|
@@ -1430,13 +1430,13 @@ merge_types(bool, {atom,A}) ->
|
|
merge_bool(A);
|
|
merge_types({atom,A}, bool) ->
|
|
merge_bool(A);
|
|
-merge_types(#ms{id=Id1,valid=B0,slots=Slots},
|
|
- #ms{id=Id2,valid=B1,slots=Slots}) ->
|
|
+merge_types(#ms{id=Id1,valid=B1,slots=Slots1},
|
|
+ #ms{id=Id2,valid=B2,slots=Slots2}) ->
|
|
Id = if
|
|
Id1 =:= Id2 -> Id1;
|
|
true -> make_ref()
|
|
end,
|
|
- #ms{id=Id,valid=B0 band B1,slots=Slots};
|
|
+ #ms{id=Id,valid=B1 band B2,slots=min(Slots1, Slots2)};
|
|
merge_types(T1, T2) when T1 =/= T2 ->
|
|
%% Too different. All we know is that the type is a 'term'.
|
|
term.
|
|
--- otp_src_20.1/lib/compiler/test/bs_match_SUITE.erl
|
|
+++ otp_src_20.1/lib/compiler/test/bs_match_SUITE.erl
|
|
@@ -39,7 +39,7 @@
|
|
match_string_opt/1,select_on_integer/1,
|
|
map_and_binary/1,unsafe_branch_caching/1,
|
|
bad_literals/1,good_literals/1,constant_propagation/1,
|
|
- parse_xml/1,get_payload/1]).
|
|
+ parse_xml/1,get_payload/1,num_slots_different/1]).
|
|
|
|
-export([coverage_id/1,coverage_external_ignore/2]).
|
|
|
|
@@ -71,7 +71,7 @@ groups() ->
|
|
match_string_opt,select_on_integer,
|
|
map_and_binary,unsafe_branch_caching,
|
|
bad_literals,good_literals,constant_propagation,parse_xml,
|
|
- get_payload]}].
|
|
+ get_payload,num_slots_different]}].
|
|
|
|
|
|
init_per_suite(Config) ->
|
|
@@ -1524,6 +1524,40 @@ do_get_payload(ExtHdr) ->
|
|
<<_:13,_:35>> = ExtHdr#ext_header.ext_hdr_opts,
|
|
ExtHdrOptions.
|
|
|
|
+%% ERL-490
|
|
+num_slots_different(_Config) ->
|
|
+ Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>},
|
|
+ {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>},
|
|
+ {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>},
|
|
+ {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>},
|
|
+ {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>},
|
|
+ {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>},
|
|
+ {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}],
|
|
+ _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts],
|
|
+
|
|
+ {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)),
|
|
+ {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)),
|
|
+ {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)),
|
|
+ {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)),
|
|
+ ok.
|
|
+
|
|
+
|
|
+lgettext(<<"de">>, <<"default">>, <<"Remove">>) ->
|
|
+ {ok, <<"a">>};
|
|
+lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) ->
|
|
+ {ok, <<"a">>};
|
|
+lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) ->
|
|
+ {ok, <<"a">>};
|
|
+lgettext(<<"de">>, <<"default">>, <<"Results">>) ->
|
|
+ {ok, <<"Ergebnisse">>};
|
|
+lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) ->
|
|
+ {ok, <<"a">>};
|
|
+lgettext(<<"de">>, <<"navigation">>, <<"Results">>) ->
|
|
+ {ok, <<"Ergebnisse">>};
|
|
+lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) ->
|
|
+ {ok, <<"Ressourcen">>}.
|
|
+
|
|
+
|
|
check(F, R) ->
|
|
R = F().
|
|
|