aboutsummaryrefslogtreecommitdiffstats
path: root/lib/compiler/src/beam_ssa_type.erl
diff options
context:
space:
mode:
authorJohn Högberg <[email protected]>2019-05-28 17:09:42 +0200
committerJohn Högberg <[email protected]>2019-06-11 15:47:38 +0200
commit2821afd35f0c7223bca45e6031ea210b4fcaa2a5 (patch)
treeea177043de0351841a3458a5941b7e9412986f04 /lib/compiler/src/beam_ssa_type.erl
parentc02fc618f98c9fb97b15aae97e11fa1c23e250fc (diff)
downloadotp-2821afd35f0c7223bca45e6031ea210b4fcaa2a5.tar.gz
otp-2821afd35f0c7223bca45e6031ea210b4fcaa2a5.tar.bz2
otp-2821afd35f0c7223bca45e6031ea210b4fcaa2a5.zip
beam_ssa_type: Fix meet/join inconsistency
meet/2 and join/2 were not entirely consistent with each other, and it was possible to meet integers that didn't overlap, producing a nonsense result. None of these can cause issues in the OTP 22 track as far as we can tell, so a patch doesn't feel necessary at this time.
Diffstat (limited to 'lib/compiler/src/beam_ssa_type.erl')
-rw-r--r--lib/compiler/src/beam_ssa_type.erl14
1 files changed, 9 insertions, 5 deletions
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
index c163d544ce..f8fefa8936 100644
--- a/lib/compiler/src/beam_ssa_type.erl
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -1860,6 +1860,9 @@ join(#t_atom{elements=[_|_]}, #t_atom{elements=any}=T) -> T;
join({binary,U1}, {binary,U2}) ->
{binary,gcd(U1, U2)};
join(#t_fun{}, #t_fun{}) -> #t_fun{};
+join(#t_integer{elements={MinA,MaxA}},
+ #t_integer{elements={MinB,MaxB}}) ->
+ #t_integer{elements={min(MinA,MinB),max(MaxA,MaxB)}};
join(#t_integer{}, #t_integer{}) -> t_integer();
join(list, cons) -> list;
join(cons, list) -> list;
@@ -1985,9 +1988,10 @@ meet(#t_integer{elements={_,_}}=T, #t_integer{elements=any}) ->
T;
meet(#t_integer{elements=any}, #t_integer{elements={_,_}}=T) ->
T;
-meet(#t_integer{elements={Min1,Max1}},
- #t_integer{elements={Min2,Max2}}) ->
- #t_integer{elements={max(Min1, Min2),min(Max1, Max2)}};
+meet(#t_integer{elements={MinA,MaxA}}, #t_integer{elements={MinB,MaxB}})
+ when MinA >= MinB, MaxA =< MaxB;
+ MinB >= MinA, MaxB =< MaxA ->
+ #t_integer{elements={max(MinA, MinB),min(MaxA, MaxB)}};
meet(#t_integer{}=T, number) -> T;
meet(float=T, number) -> T;
meet(number, #t_integer{}=T) -> T;
@@ -1999,7 +2003,7 @@ meet(nil, list) -> nil;
meet(#t_tuple{}=T1, #t_tuple{}=T2) ->
meet_tuples(T1, T2);
meet({binary,U1}, {binary,U2}) ->
- {binary,max(U1, U2)};
+ {binary, U1 * U2 div gcd(U1, U2)};
meet(any, T) ->
verified_type(T);
meet(T, any) ->
@@ -2073,7 +2077,7 @@ verified_type({binary,U}=T) when is_integer(U) -> T;
verified_type(#t_fun{arity=Arity}=T) when Arity =:= any; is_integer(Arity) -> T;
verified_type(#t_integer{elements=any}=T) -> T;
verified_type(#t_integer{elements={Min,Max}}=T)
- when is_integer(Min), is_integer(Max) -> T;
+ when is_integer(Min), is_integer(Max), Min =< Max -> T;
verified_type(list=T) -> T;
verified_type(map=T) -> T;
verified_type(nil=T) -> T;