diff options
author | Björn Gustavsson <bjorn@erlang.org> | 2022-01-30 08:15:36 +0100 |
---|---|---|
committer | Björn Gustavsson <bjorn@erlang.org> | 2022-01-31 14:15:27 +0100 |
commit | a94a627208c12a9a382b5fc2fc2a881ee150ffe2 (patch) | |
tree | da00dd698930b47ee76504291a5b8f1c41f8c4c4 /lib/compiler/src/beam_validator.erl | |
parent | e818258f84fbecf232797df5d71ee46e23a43391 (diff) | |
download | erlang-a94a627208c12a9a382b5fc2fc2a881ee150ffe2.tar.gz |
beam_ssa_type: Infer the type for a tuple used as a lookup table
Find the type of a call to `erlang/2` where a literal tuple is
used as a lookup table. Here is a truncated example from the
`base64` module:
element(X+1, {$A, $B, $C, $D, $E, $F, ...})
The type will be the join of the types of the elements.
Diffstat (limited to 'lib/compiler/src/beam_validator.erl')
-rw-r--r-- | lib/compiler/src/beam_validator.erl | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index adbddc7059..63b2dc9e07 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -3055,7 +3055,28 @@ assert_not_fragile(Lit, #vst{}) -> bif_types(Op, Ss, Vst) -> Args = [normalize(get_term_type(Arg, Vst)) || Arg <- Ss], - beam_call_types:types(erlang, Op, Args). + case {Op,Ss} of + {element,[_,{literal,Tuple}]} when tuple_size(Tuple) > 0 -> + case beam_call_types:types(erlang, Op, Args) of + {any,ArgTypes,Safe} -> + RetType = join_tuple_elements(Tuple), + {RetType,ArgTypes,Safe}; + Other -> + Other + end; + {_,_} -> + beam_call_types:types(erlang, Op, Args) + end. + +join_tuple_elements(Tuple) -> + join_tuple_elements(tuple_size(Tuple), Tuple, none). + +join_tuple_elements(0, _Tuple, Type) -> + Type; +join_tuple_elements(I, Tuple, Type0) -> + Type1 = beam_types:make_type_from_value(element(I, Tuple)), + Type = beam_types:join(Type0, Type1), + join_tuple_elements(I - 1, Tuple, Type). call_types({extfunc,M,F,A}, A, Vst) -> Args = get_call_args(A, Vst), |