aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_validator.erl
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2019-07-04 11:28:03 +0200
committerJohn Högberg <[email protected]>2019-07-05 15:55:56 +0200
commit8fcf04006643c70078035c9af5245e3be0c33108 (patch)
tree1a666dfc864eb51c962b014d31f07b399245f219 /lib/compiler/src/beam_validator.erl
parentb2de9af91c1dc2dc4188986bf7a63fe48c045c33 (diff)
downloadotp-8fcf04006643c70078035c9af5245e3be0c33108.tar.gz
otp-8fcf04006643c70078035c9af5245e3be0c33108.tar.bz2
otp-8fcf04006643c70078035c9af5245e3be0c33108.zip
beam_ssa_type: Infer types on switch failure
If we know that the checked value is a singleton at the fail block, it's safe to infer types as if we've made a direct comparison against that value.
Diffstat (limited to 'lib/compiler/src/beam_validator.erl')
-rw-r--r--lib/compiler/src/beam_validator.erl22
1 files changed, 21 insertions, 1 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index 923a0b4a4e..afede2b54d 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -1531,8 +1531,21 @@ validate_select_val(Fail, [Val,{f,L}|T], Src, Vst0) ->
update_ne_types(Src, Val, FailVst)
end),
validate_select_val(Fail, T, Src, Vst);
-validate_select_val(Fail, [], _, Vst) ->
+validate_select_val(Fail, [], Src, Vst) ->
branch(Fail, Vst,
+ fun(FailVst) ->
+ FailType = get_term_type(Src, FailVst),
+ case beam_types:get_singleton_value(FailType) of
+ {ok, Value} ->
+ %% This is the only possible value at the fail
+ %% label, so we can infer types as if we matched it
+ %% directly.
+ Lit = value_to_literal(Value),
+ update_eq_types(Src, Lit, FailVst);
+ error ->
+ FailVst
+ end
+ end,
fun(SuccVst) ->
%% The next instruction is never executed.
kill_state(SuccVst)
@@ -1921,6 +1934,13 @@ is_literal({integer,I}) when is_integer(I) -> true;
is_literal({literal,_L}) -> true;
is_literal(_) -> false.
+%% `dialyzer` complains about the float and general literal cases never being
+%% matched and I don't like suppressing warnings. Should they become possible
+%% I'm sure `dialyzer` will warn about it.
+value_to_literal([]) -> nil;
+value_to_literal(A) when is_atom(A) -> {atom,A};
+value_to_literal(I) when is_integer(I) -> {integer,I}.
+
%% These are just wrappers around their equivalents in beam_types, which
%% handle the validator-specific #t_abstract{} type.
%%