-
Notifications
You must be signed in to change notification settings - Fork 3k
Improve the type analysis #5999
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve the type analysis #5999
Conversation
CT Test Results 4 files 367 suites 43m 42s ⏱️ For more details on these failures, see this check. Results for commit c412a61. ♻️ This comment has been updated with latest results. To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts// Erlang/OTP Github Action Bot |
But isn't this particular human wrong? (Because |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
But isn't this particular human wrong?
(Because
A
can also be a float. Figuring out thatA
must be a number is OK though.)
There's an is_integer/1
test hiding in the first example. :-)
Yes, I need new glasses :( |
7dcd4e2
to
249aef8
Compare
098e03a
to
431545e
Compare
Refactor the type analysis modules in the Erlang compiler to be able to derive type information from relational operators in guards. Consider this function: f(A) when is_integer(A), 0 =< A, A =< 1000 -> A + 1. From the guard, a human can easily figure out that `A` must be an integer in the range 0 through 1000. The compiler in OTP 25 cannot: {test,is_integer,{f,1},[{x,0}]}. {test,is_ge,{f,1},[{tr,{x,0},{t_integer,any}},{integer,0}]}. {test,is_ge,{f,1},[{integer,1000},{tr,{x,0},{t_integer,any}}]}. {gc_bif,'+',{f,0},1,[{tr,{x,0},{t_integer,any}},{integer,1}],{x,0}}. With this commit, the compiler generates the following code: {test,is_integer,{f,1},[{x,0}]}. {test,is_ge,{f,1},[{tr,{x,0},{t_integer,any}},{integer,0}]}. {test,is_ge,{f,1},[{integer,1000},{tr,{x,0},{t_integer,{0,'+inf'}}}]}. {gc_bif,'+',{f,0},1,[{tr,{x,0},{t_integer,{0,1000}}},{integer,1}],{x,0}}. The compiler can now also derive better types for the following function: g(A) when 0 =< A, A =< 1000 -> A + 1. Since `A` is sandwiched between two numbers, `A` must be a number: {test,is_ge,{f,3},[{x,0},{integer,0}]}. {test,is_ge, {f,3}, [{integer,1000}, {tr,{x,0}, {t_union,{t_atom,any}, {t_list,any,any}, {t_number,{0,'+inf'}}, {t_tuple,0,false,#{}}, other}}]}. {gc_bif,'+',{f,0},1,[{tr,{x,0},{t_number,{0,1000}}},{integer,1}],{x,0}}. The JIT will generate slightly better code for known numeric operands than for unknown operands. As part of this commit, the following major changes were made: * Ranges for integers can now extend to infinity at one endpoint. That is, a range can go from negative infinity to some integer, or from some integer to positive infinity. That change allows the compiler to represent the type for the variable `A` when `A` is known to be an integer and `A >= 0` is true. * Changed the number type to also include a (potentially infinite) range. * Introduced an `other` type as a mean to construct a union type that is equivalent to the `any` type. That makes it possible to represent the type for `A` when all we know is that `A >= 0` (see the type in in the second `is_ge` test in the generated code for `g/1` above). * The API for the `beam_bounds` module was changed to avoid having to create functions with the same name as operators and BIFs. Having functions named `min` and `max` in the module would have been error-prone and painful.
c412a61
to
92611e5
Compare
Refactor the type analysis modules in the Erlang compiler to
be able to derive type information from relational operators
in guards.
Consider this function:
From the guard, a human can easily figure out that
A
must bean integer in the range 0 through 1000. The compiler in OTP 25
cannot:
With this pull request, the compiler generates the following code:
The compiler can now also derive better types for the following function:
Since
A
is sandwiched between two numbers,A
must be a number:The JIT will generate slightly better code for known numeric operands than
for unknown operands.
As part of this commit, the following major changes were made:
Ranges for integers can now extend to infinity at one endpoint. That
is, a range can go from negative infinity to some integer, or from
some integer to positive infinity. That change allows the compiler to
represent the type for the variable
A
whenA
is known to be aninteger and
A >= 0
is true.Changed the number type to also include a (potentially infinite) range.
Introduced an
other
type as a mean to construct a union type thatis equivalent to the
any
type. That makes it possible to representthe type for
A
when all we know is thatA >= 0
(see the type inin the second
is_ge
test in the generated code forg/1
above).The API for the
beam_bounds
module was changed to avoid having tocreate functions with the same name as operators and BIFs. Having
functions named
min
andmax
in the module would have beenerror-prone and painful.