From 2821afd35f0c7223bca45e6031ea210b4fcaa2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Tue, 28 May 2019 17:09:42 +0200 Subject: 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. --- lib/compiler/src/beam_ssa_type.erl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'lib/compiler/src') 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; -- cgit v1.2.3