Skip to content

Commit

Permalink
beam_validator: Support subtraction in update_container_type/4
Browse files Browse the repository at this point in the history
  • Loading branch information
jhogberg committed Apr 27, 2021
1 parent 1eb7ac2 commit ba43dcc
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
16 changes: 11 additions & 5 deletions lib/compiler/src/beam_validator.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2093,7 +2093,7 @@ update_type(Merge, With, #value_ref{}=Ref, Vst0) ->
none ->
throw({type_conflict, Current, With});
Type ->
Vst = update_container_type(Type, Ref, Vst0),
Vst = update_container_type(Merge, With, Ref, Vst0),
set_type(Type, Ref, Vst)
end;
update_type(Merge, With, {Kind,_}=Reg, Vst) when Kind =:= x; Kind =:= y ->
Expand All @@ -2108,13 +2108,19 @@ update_type(Merge, With, Literal, Vst) ->
end.

%% Updates the container the given value was extracted from, if any.
update_container_type(Type, Ref, #vst{current=#st{vs=Vs}}=Vst) ->
update_container_type(Merge, With, Ref, #vst{current=#st{vs=Vs}}=Vst) ->
case Vs of
#{ Ref := #value{op={bif,element},
args=[{integer,Index},Tuple]} } when Index >= 1 ->
Es = beam_types:set_tuple_element(Index, Type, #{}),
TupleType = #t_tuple{size=Index,elements=Es},
update_type(fun meet/2, TupleType, Tuple, Vst);
case beam_types:set_tuple_element(Index, With, #{}) of
#{ Index := _ }=Es ->
TupleType = #t_tuple{size=Index,elements=Es},
update_type(Merge, TupleType, Tuple, Vst);
#{} ->
%% Index was above the element limit; subtract/2 won't be
%% safe and meet/2 won't do anything.
Vst
end;
#{} ->
Vst
end.
Expand Down
27 changes: 25 additions & 2 deletions lib/compiler/test/beam_type_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1,
arity_checks/1,elixir_binaries/1,find_best/1,
test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1,
none_argument/1,success_type_oscillation/1,type_subtraction/1]).
none_argument/1,success_type_oscillation/1,type_subtraction/1,
container_subtraction/1]).

%% Force id/1 to return 'any'.
-export([id/1]).

suite() -> [{ct_hooks,[ts_install_cth]}].

Expand Down Expand Up @@ -53,7 +57,8 @@ groups() ->
bad_binary_unit,
none_argument,
success_type_oscillation,
type_subtraction
type_subtraction,
container_subtraction
]}].

init_per_suite(Config) ->
Expand Down Expand Up @@ -633,5 +638,23 @@ ts_23(_x@1) ->
2
end.

%% GH-4774: The validator didn't update container contents on type subtraction.
container_subtraction(Config) when is_list(Config) ->
A = id(baz),

cs_1({foo,[]}),
cs_1({bar,A}),
cs_2({bar,A}),

ok.

cs_1({_,[]}) ->
ok;
cs_1({_,_}=Other) ->
cs_2(Other).

cs_2({bar,baz}) ->
ok.

id(I) ->
I.

0 comments on commit ba43dcc

Please sign in to comment.