Skip to content

Commit c4b9509

Browse files
committed
Enhance type inference for non-literal ranges
1 parent a211a3a commit c4b9509

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

lib/compiler/src/beam_ssa_type.erl

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2721,6 +2721,15 @@ make_number({'-inf','+inf'}) ->
27212721
make_number({_,_}=R) ->
27222722
#t_number{elements=R}.
27232723

2724+
make_integer({'-inf','+inf'}) ->
2725+
#t_integer{};
2726+
make_integer({'-inf',_}=R) ->
2727+
#t_integer{elements=R};
2728+
make_integer({Min,Max}=R) when is_integer(Min), Min =< Max ->
2729+
#t_integer{elements=R};
2730+
make_integer(_) ->
2731+
#t_integer{}.
2732+
27242733
inv_relop({bif,Op}) -> inv_relop_1(Op);
27252734
inv_relop(_) -> none.
27262735

@@ -2736,6 +2745,16 @@ infer_get_range(#t_integer{elements=R}) -> R;
27362745
infer_get_range(#t_number{elements=R}) -> R;
27372746
infer_get_range(_) -> unknown.
27382747

2748+
infer_integer_get_range(Arg, Ts) ->
2749+
case concrete_type(Arg, Ts) of
2750+
#t_integer{elements={_,_}=R} ->
2751+
R;
2752+
#t_number{elements={Min,Max}=R}
2753+
when is_integer(Min), is_integer(Max) -> R;
2754+
_ ->
2755+
{'-inf','+inf'}
2756+
end.
2757+
27392758
infer_br_value(_V, _Bool, none) ->
27402759
none;
27412760
infer_br_value(V, Bool, NewTs) ->
@@ -2819,18 +2838,12 @@ infer_type({bif,is_integer}, [#b_var{}=Arg,
28192838
#b_literal{val=Max}], _Ts, _Ds) when Min =< Max ->
28202839
T = {Arg, beam_types:make_integer(Min, Max)},
28212840
{[T], [T]};
2822-
infer_type({bif,is_integer}, [#b_var{}=Arg,
2823-
#b_literal{val=Min},_], _Ts, _Ds) ->
2824-
T = {Arg, make_number({Min,'+inf'})},
2825-
{[T], [T]};
2826-
infer_type({bif,is_integer}, [#b_var{}=Arg,_,
2827-
#b_literal{val=Max}], _Ts, _Ds) ->
2828-
T = {Arg, make_number({'-inf',Max})},
2829-
{[T], [T]};
2830-
infer_type({bif,is_integer}, [#b_var{}=Arg, _, _], _Ts, _Ds) ->
2831-
%% We cannot subtract the type when the bounds are unknown: `Arg` may still
2832-
%% be an integer if it is not in the tested range.
2833-
T = {Arg, #t_integer{}},
2841+
infer_type({bif,is_integer}, [#b_var{}=Arg,Min0,Max0], Ts, _Ds) ->
2842+
{Min,_} = infer_integer_get_range(Min0, Ts),
2843+
{_,Max} = infer_integer_get_range(Max0, Ts),
2844+
T = {Arg, make_integer({Min,Max})},
2845+
%% Conservatively never attempt to subtract the type; subtraction
2846+
%% will most likely be incorrect or useless.
28342847
{[T], []};
28352848
infer_type({bif,is_list}, [#b_var{}=Arg], _Ts, _Ds) ->
28362849
T = {Arg, #t_list{}},

0 commit comments

Comments
 (0)