When left side is expanded but become invalid, the expansion result in the AST leaking for the user, for example:
```
iex(1)> __ENV__.line.foo
{{:., [line: 1], [1, :foo]}, [line: 1], []}
```
This checks the expanded left to ensure that it's safe
Consider the following example:
defmodule NestedQuote do
defmacrop macro(arg) do
quote bind_quoted: [arg: arg] do
quote bind_quoted: [arg: arg], do: String.duplicate(arg, 2)
end
end
defmacro __using__(_) do
quote do
def test do
unquote(macro("foo"))
end
end
end
end
defmodule UseNestedQuote do
use NestedQuote
end
It has two macro expansions, one inside __using__/1 when it invokes
macro/1, and another when used. The issue, however, is that the
`arg` of `String.duplicate(arg, 2)` gets tagged with the context
of `macro/1` but it should be tagged with the context of `__using__`
since it is a quote inside a quote. This patch addresses this.
Until now, we left rewriting operators in matches to Erlang. This forced
us to inherit Erlang semantics, especially for the ++ operator, that
only allows lists of integers on the left side inside matches. The new
implementation just rewrites this operator regular improper list matching.
Additionally we rewrite matching on -/1 and +/1 operators to number
literals - matching with those operators and variables was never
supported.
Additionally do a bit of housekeeping and refactor code around rewriting
and validating remote calls.
Unfortunately it is common to have macros that invokes macros
from other modules, leading to mixed quoted expressions causing
the counters to be mixed.
We would need to scope the counters to the caller.
This reverts commit f04f46c49d.
When the module is being compiled, we use deterministic counters instead
of random ones. This should help with most cases of undeterministic
source code or .beam files.
Closes#7955
We use this option in ExUnit as we are escaping
the code to eventually convert it to a string
representation and therefore the metadata is not
relevant.
This siwtches protocol compilation to happen on the epxnaded Elixir AST
instead of the Erlang AST. This is slightly less complex and opens
possibility for easy "partial" compilation of protocols.
Additionally instead of rewriting specs on consolidation, this marks the
functions that end-up being rewritten with @dialyzer :nowarn_function to
disable overly eager dialyzer warnings.