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.
Erlang/OTP 20 warns if the stacktrace is read outside of a
catch/rescue. This commit mirrors this behaviour by consistently
warning on `System.stacktrace/0` being used outside of a
catch/rescue.
Erlang/OTP 21 warns whenever System.stacktrace/:erlang.get_stacktrace
are used. Therefore we need to promote the usage of `__STACKTRACE__`
and make sure to conditionally compile it according to the OTP version.
This requires changes to the Exception normalization mechanism
so we compute `__STACKTRACE__` only when strictly required.
In future Elixir releases, `System.stacktrace/0` will warn when
used even inside catch/rescue.
elixir_rewrite.erl has been audited, function by function:
- All missing "Inlined by the compiler." lines have been added.
- Standardize sentence avoid mentioning the function its inline to (System module).
- "Inline by the compiler." goes always before ##Options or ##Examples
Reason to add it is capturing functions when passing in module name,
function name and arity using variable, because the capture operator
can't handle them.
Done by delegating to `:erlang.make_fun(mod, f, arity)`, also exposed
some erlang functions for getting information for a function.
Change how we mark the generated AST for suppressing dialyzer errors -
instead of [generated: true, location: 0], we provide proper line number.
This means, however, that on OTP 18, those nodes won't be recognized
as generated and warnings will be issued.
It was decided that proper error messages are more important than
avoiding bogus dialyzer warnings.
The old mark for generated code is left in places that made compiler
issue warnings on 18.
The bad remote call dialyzer warnings can be suppressed with the
@dialyzer :no_fail_call
module attribute.