aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2019-04-23 07:40:48 +0200
committerJohn Högberg <[email protected]>2019-04-23 11:50:00 +0200
commit64a6cdc80e2f3c33c3cb18b41721b2738337cb56 (patch)
tree56c13f46c5009281733d241f175717663759fcff
parent90eb43d0b61b5a51aede0537e394bd02216b6fa0 (diff)
downloadotp-64a6cdc80e2f3c33c3cb18b41721b2738337cb56.tar.gz
otp-64a6cdc80e2f3c33c3cb18b41721b2738337cb56.tar.bz2
otp-64a6cdc80e2f3c33c3cb18b41721b2738337cb56.zip
beam_validator: Don't infer types for dead values
-rw-r--r--lib/compiler/src/beam_validator.erl22
-rw-r--r--lib/compiler/test/beam_validator_SUITE.erl25
2 files changed, 41 insertions, 6 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index efd2be94cb..09a5a6c104 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1604,8 +1604,13 @@ infer_types_1(#value{op={bif,'=:='},args=[LHS,RHS]}) ->
end;
infer_types_1(#value{op={bif,element},args=[{integer,Index}=Key,Tuple]}) ->
fun(Val, S) ->
- Type = get_term_type(Val, S),
- update_type(fun meet/2,{tuple,[Index],#{ Key => Type }}, Tuple, S)
+ case is_value_alive(Tuple, S) of
+ true ->
+ Type = {tuple,[Index], #{ Key => get_term_type(Val, S) }},
+ update_type(fun meet/2, Type, Tuple, S);
+ false ->
+ S
+ end
end;
infer_types_1(#value{op={bif,is_atom},args=[Src]}) ->
infer_type_test_bif({atom,[]}, Src);
@@ -1629,7 +1634,10 @@ infer_types_1(#value{op={bif,is_tuple},args=[Src]}) ->
infer_type_test_bif({tuple,[0],#{}}, Src);
infer_types_1(#value{op={bif,tuple_size}, args=[Tuple]}) ->
fun({integer,Arity}, S) ->
- update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S);
+ case is_value_alive(Tuple, S) of
+ true -> update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S);
+ false -> S
+ end;
(_, S) -> S
end;
infer_types_1(_) ->
@@ -1637,7 +1645,10 @@ infer_types_1(_) ->
infer_type_test_bif(Type, Src) ->
fun({atom,true}, S) ->
- update_type(fun meet/2, Type, Src, S);
+ case is_value_alive(Src, S) of
+ true -> update_type(fun meet/2, Type, Src, S);
+ false -> S
+ end;
(_, S) ->
S
end.
@@ -2274,6 +2285,9 @@ get_raw_type(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) ->
get_raw_type(Src, #vst{}) ->
get_literal_type(Src).
+is_value_alive(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) ->
+ is_map_key(Ref, Vs).
+
get_literal_type(nil=T) -> T;
get_literal_type({atom,A}=T) when is_atom(A) -> T;
get_literal_type({float,F}=T) when is_float(F) -> T;
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl
index de5a3c2873..6b1438abdd 100644
--- a/lib/compiler/test/beam_validator_SUITE.erl
+++ b/lib/compiler/test/beam_validator_SUITE.erl
@@ -35,7 +35,7 @@
map_field_lists/1,cover_bin_opt/1,
val_dsetel/1,bad_tuples/1,bad_try_catch_nesting/1,
receive_stacked/1,aliased_types/1,type_conflict/1,
- infer_on_eq/1]).
+ infer_on_eq/1,infer_dead_value/1]).
-include_lib("common_test/include/ct.hrl").
@@ -65,7 +65,7 @@ groups() ->
map_field_lists,cover_bin_opt,val_dsetel,
bad_tuples,bad_try_catch_nesting,
receive_stacked,aliased_types,type_conflict,
- infer_on_eq]}].
+ infer_on_eq,infer_dead_value]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -679,6 +679,27 @@ infer_on_eq_4(T) ->
true = erlang:tuple_size(T) =:= 1,
{ok, erlang:element(1, T)}.
+%% ERIERL-348; types were inferred for dead values, causing validation to fail.
+
+infer_dead_value(Config) when is_list(Config) ->
+ a = idv_1({a, b, c, d, e, f, g}, {0, 0, 0, 0, 0, 0, 0}),
+ b = idv_1({a, b, c, d, 0, 0, 0}, {a, b, c, d, 0, 0, 0}),
+ c = idv_1({0, 0, 0, 0, 0, f, g}, {0, 0, 0, 0, 0, f, g}),
+ error = idv_1(gurka, gaffel),
+ ok.
+
+idv_1({_A, _B, _C, _D, _E, _F, _G},
+ {0, 0, 0, 0, 0, 0, 0}) ->
+ a;
+idv_1({A, B, C, D,_E, _F, _G}=_Tuple1,
+ {A, B, C, D, 0, 0, 0}=_Tuple2) ->
+ b;
+idv_1({_A, _B, _C, _D, _E, F, G},
+ {0, 0, 0, 0, 0, F, G}) ->
+ c;
+idv_1(_A, _B) ->
+ error.
+
%%%-------------------------------------------------------------------------
transform_remove(Remove, Module) ->