Optimizes :maps.put/3 to a VM operation instead of a remote call, including nested calls to it.
It does the same for :maps.merge/2 with a simple map on the right side.
Closes#7353
The optimize_boolean option is very sensitive to the order of
clauses and the optimisation was not happening for and/2 and or/2.
Add regression tests to ensure that won't happen again.
Removes tests that dialyzer does not emit warnings for optimised
and and or - those warnings could actually be helpful.
When you are working on large files and you add new code,
you may forget to add a `do` or an `end`. In those cases,
the error message usually points to the first `do` or the
last `end` in the file, which are usually far away from
the source of the error.
This pull request adds a simple heuristic based on the
indentation of the tokens, to try to provide hints of
where the source may be. Those hints are not deterministic
but they may be able to point users to the source of the
problem.
For example, in this case:
defmodule MyApp do
def one do
# end
def two do
end
end
we know that we now that `def two do` is happening on the
same indentation as `def one do`, which may mean that
`def one do` was not closed properly. We store this as a
hint in case the terminators do not match later.
Similarly, in the case below:
defmodule MyApp do
def one
end
def two do
end
end
The `end` on line 3 will end-up closing the defmodule `do`,
on line 1. Because their indentation do not match, it may
be that there is a missing `do`, where the `end` was supposed
to align.
Some basic testing show those heuristics work on the majority
of the cases, but we will only be sure when we have enough
feedback from the community.
This gives us better control over when and how unused variables are printed.
As a result, we are able to emit unused variable warnings in situations
we could not before. This also opens up the way for us to remove a
dependency on erl_lint and track types information, which allows us to
speed up compilation times about 5% and allow us to emit more performant
code in some situations.
Right now, tokens are "{Token, Location}" or "{Token, Location, Value}".
This commit changes "Location" from "{Line, StartColumn, EndColumn}" to
"{Line, {StartColumn, EndColumn}, Meta}" where "Meta" can be anything.
This will be used for things such as storing the format of integers.
orelse may lead to better code in many occasions - Since we're comparing
to literals, there's no semantic difference.
This also means, the compiler is able to figure out more "will always match"
checks. For example in a situation like the following a warning will be emitted.
This pull request also fixes such warnings in the test suite.
if true do
IO.puts("true")
end
One problem with using `orelse` is that it will short-circuit and not evaluate
some side-effecting things, for example:
1 in [1, send(self(), :foo)]
To remedy this, we'll traverse the right side of `in` and extract any things
that are not simple literals to variables, so that the above example expands
to something like the following:
var0 = send(seld(), :foo)
var = 1
var === 1 or var === var0
This guarantees all side-effects are performed and we still retain benefits of
the short-circuiting comparisons in the end.
For providing better feedback in credo and tools like it we should be
able to map a token back to its original source. This makes sure that
`_` characters in numbers are properly accounted for so that they stay
in sync after we've encountered something like 123_456_789.
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>