Age | Commit message (Collapse) | Author |
|
This fixes a regression introduced in commit 805f9c89fc01220bc1bb0f27e1b68fd4eca688ba
The problem occured with map keys compiled with dialyzer option turned on.
In OTP 17, map keys needs to be literals.
|
|
A module containing two named funs bearing the same name and arity could be
miscompiled.
Reported-by: Sam Chapin
|
|
|
|
This ticket is about records in Erlang code, and when to check the
fields against the (optional) types given when defining records.
Dialyzer operates on the Erlang Core format, where there are no trace
of records. The fix implemented is a Real Hack:
Given the new option 'dialyzer' erl_expand_records marks the line
number of records in a way that is undone by v3_core, which in turn
inserts annotations that can be recognized by Dialyzer.
|
|
|
|
Map keys with large (non literal) binary keys must fail.
|
|
Even if a binary key is written as a literal the compiler may
choose to make an expression. Emit a warning in those cases
and saying the case will not match.
This is a limitation in current implementation.
|
|
Reported-by: José Valim
|
|
Core should not understand M#{}
Instead transform M#{} to
case _cor0 of
<_cor1>
when call 'erlang':'is_map'
(_cor0) ->
_cor1
( <_cor2> when 'true' ->
primop 'match_fail'
('badarg')
-| ['compiler_generated'] )
end
|
|
Reject all expressions that are known to fail.
Emit 'badarg' for those expressions.
Ex.
[]#{ a => 1}
Is not a valid map update expression.
|
|
|
|
* nox/compiler/v3_core-comprehension-no-export:
Do not export variables from comprehension cases in v3_core
OTP-11770
|
|
Code like the following snippet could make the compiler crash:
f() -> [X = a || false] ++ [X = a || false].
Reported-by: Ulf Norell
|
|
Previously, erlang:'or'(X, Y) and X or Y were not compiled to the same
Core code.
|
|
(fun f/1)() should be compiled to let X = 'f'/1 in apply X () to let the compiler
properly generate code that will fail with badarity at runtime.
Reported-by: Ulf Norell
|
|
* egil/compiler/maps-get_map_elements:
compiler: Strengthen Maps compile tests
compiler: Remove dead warning
erts: Fix erts_debug:disassemble/1
compiler: Transform list of Args to exact literal type
compiler: Test Maps aliasing
compiler: Use aliasing in map pair patterns
compiler: Check literal order in beam_validator
erts: Introduce new instructions for combined key fetches
compiler: Change map instructions for fetching values
|
|
|
|
Given that map comprehensions and generators and maybe && generators will be added
to the language in the future, v3_core:lc_tq and v3_core:bc_tq could use a rewrite
to avoid a complexity explosion, where there are as many related clauses as the
product of the number of types of generators and the number of types of
comprehensions.
The new code abstract over all generators at the same time, there is only one clause
for generators per type of comprehension, and all the filter code has been put
in a common function filter_tq.
It should also be noted that generator inputs are now compiled before the rest
of the qualifiers, reversing names of nested comprehensions.
|
|
* 'bjorn/lc-warnings/OTP-11626' (early part):
v3_core: Annotate list comprehensions to help out dialyzer
|
|
* hsv/using_lists_droplast:
lib/mnesia/test/ - Replace reverse(tl(reverse(L))) with lists:droplast/1
lib/ssh - Replace reverse(tl(reverse(L))) with lists:droplast/1
lib/wx - Replace reverse(tl(reverse(L))) with lists:droplast/1
Use lists:droplast/1 in orber/orber_interceptors.erl
Import and use lists:droplast/1 in v3_core/v3_kernel
OTP-11678
OTP-11677
|
|
|
|
|
|
Simplify compiler internals and parsing of core format.
|
|
Make map update expressions safe, i.e. (foo())#{ k1 := 1 }
|
|
The syntax is handled upto v3_kernel where it is reduced to
previous behaviour for construction and updates. Meaning,
the ':=' operator is handled exactly as '=>' operator.
|
|
|
|
To make it possible to build the entire OTP system, also define
dummys for the instructions in ops.tab.
|
|
Also imported lists:last/1, and removed the local definition.
|
|
Because 26940a8c0c lifted code in the 'after' clause of 'try' to
a new function, Dialyzer could produce false warnings for code such
as:
try
...
after
file:close(F)
end.
Mark the the call to the generated function as 'compiler_generated'
to silence the warning.
|
|
This adds optional names to fun expressions. A named fun expression
is parsed as a tuple `{named_fun,Loc,Name,Clauses}` in erl_parse.
If a fun expression has a name, it must be present and be the same in
every of its clauses. The function name shadows the environment of the
expression shadowing the environment and it is shadowed by the
environment of the clauses' arguments. An unused function name triggers
a warning unless it is prefixed by _, just as every variable.
Variable _ is allowed as a function name.
It is not an error to put a named function in a record field default
value.
When transforming to Core Erlang, the named fun Fun is changed into
the following expression:
letrec 'Fun'/Arity =
fun (Args) ->
let <Fun> = 'Fun'/Arity
in Case
in 'Fun'/Arity
where Args is the list of arguments of 'Fun'/Arity and Case the
Core Erlang expression corresponding to the clauses of Fun.
This transformation allows us to entirely skip any k_var to k_local
transformation in the fun's clauses bodies.
|
|
|
|
* nox/lift-after/OTP-11267:
Lift 'after' blocks to zeroary functions
|
|
files as delimiters.
While working on a tool that processes Erlang code and testing it against this repo,
I found out about those little sneaky 0xff. I thought it may be of help to other
people build such tools to remove non-conforming-to-standard characters.
|
|
Conflicts:
bootstrap/lib/compiler/ebin/v3_core.beam
|
|
* nox/fix-comp-warnings/OTP-11212:
Bootstrap
Silence a misleading warning with some comprehensions
|
|
If 'after' blocks are not lifted, the ids of functions in their bodies
must be killed and it can make stacktraces more confusing than they
should. We lift them to zeroary functions to avoid unnecessary killings
and duplication of code.
|
|
* nox/illegal-bitstring-gen-pattern/OTP-11186:
Bootstrap added
Simplify v3_core's translation of bit string generators
Forbid unsized fields in patterns of binary generators
|
|
|
|
When compiling comprehensions with generators which are foldable to
'true', a misleading warning is emitted by sys_core_fold because a
clause resulting from the compilation of the comprehension to Core
Erlang is not marked as generated by the compiler.
An example of such a comprehension is [ true || true ].
|
|
Now that unsized binary segments are forbidden in patterns of bit string
generators, v3_core:append_tail_segment/2 does not need to check for an
existing unsized tail segment and can thus be changed to a simple '++'/2
call.
|
|
If a variable bound in a generator is used as the size of a segment
in the comprehension body, v3_core uses this variable in the code
generated to compute the initial size given to the `bs_init_writable`
primop before the variable is actually bound, as in:
<< <<0:S>> || S <- Slist >>
Reported-By: Peer Stritzinger
|
|
The compiler would silently accept and Dialyzer would crash on
code like:
<<X:(2.5)>>
It is never acceptable for Dialyzer to crash. The compiler should
at least generate a warning for such code. It is tempting to let
the compiler generate an error, but that would mean that code like:
Sz = 42.0,
<<X:Sz>>.
would be possible to compile with optimizations disabled, but not
with optimizations enabled.
Dialyzer crashes because it calls cerl:bitstr_bitsize/1, which
crashes if the type of size for the segment is invalid. The easiest
way to avoid that crash is to extend the sanity checks in v3_core
to also include the size field of binary segments. That will cause
the compiler to issue a warning and to replace the bad binary
construction with a call to erlang:error/1. (It also means that
Dialyzer will not issue a warning for bad size fields.)
|
|
|
|
In Core Erlang and later passes, compiler-generated code can be
indicated in two different ways: by negative line numbers and by
a 'compiler_generated' annotation.
Simplify the code and improve coverage by turning negative line
numbers positive and adding a 'compiler_generated' annotation in
the v3_core pass. That means that Core Erlang and latter passes
do not have deal with negative line numbers.
|
|
Currently, the external fun syntax "fun M:F/A" only supports
literals. That is, "fun lists:reverse/1" is allowed but not
"fun M:F/A".
In many real-life situations, some or all of M, F, A are
not known until run-time, and one is forced to either use
the undocumented erlang:make_fun/3 BIF or to use a
"tuple fun" (which is deprecated).
EEP-23 suggests that the parser (erl_parse) should immediately
transform "fun M:F/A" to "erlang:make_fun(M, F, A)". We have
not followed that approach in this implementation, because we
want the abstract code to mirror the source code as closely
as possible, and we also consider erlang:make_fun/3 to
be an implementation detail that we might want to remove in
the future.
Instead, we will change the abstract format for "fun M:F/A" (in a way
that is not backwards compatible), and while we are at it, we will
move the translation from "fun M:F/A" to "erlang:make_fun(M, F, A)"
from sys_pre_expand down to the v3_core pass. We will also update
the debugger and xref to use the new format.
We did consider making the abstract format backward compatible if
no variables were used in the fun, but decided against it. Keeping
it backward compatible would mean that there would be different
abstract formats for the no-variable and variable case, and tools
would have to handle both formats, probably forever.
Reference: http://www.erlang.org/eeps/eep-0023.html
|
|
|
|
|
|
In the following code:
m(<<Sz:8,_:Sz/binary>>) ->
Sz = wrong.
the Sz variable is supposed to be bound in the function header and the
matching "Sz = wrong" should cause a badarg exception. But what
happens is that the Sz variables seems to be unbound and the matching
succeds and the m/1 function returns 'wrong'.
If the Sz variable is used directly (not matched), it will have
the expected value. Thus the following code:
m(<<Sz:8,_:Sz/binary>>) ->
Sz.
will correctly return the value of Sz that was matched out from
the binary.
Reported-by: Bernard Duggan
|
|
|
|
In binary matching, there must only be one "tail segment" (i.e.
a size-less segment of type binary) and it must be last. Thus,
the compiler will reject the following function definition:
foo(<<A/bits,B/bits>>) -> ok.
But code such as the following:
[42 || <<_:8/integer, _/bits>> <= Bits]
will internally (in the Core Erlang format) be translated to a
binary matching pattern containing two tail segments. The compiler
happens to generate correct code anyway (later passes will get
rid of the redundant tail segment), but it is ugly and will
confuse tools such as Dialyzer.
Change the transformation of binary generators (in both list and
binary comprehensions) not to generate add a tail segment if there
already is one.
|