Skip to content

Commit cba7c5b

Browse files
author
José Valim
committed
Only expand __ENV__.call if it is a known function
1 parent 9b22b6d commit cba7c5b

File tree

5 files changed

+25
-5
lines changed

5 files changed

+25
-5
lines changed

lib/elixir/lib/macro.ex

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,13 @@ defmodule Macro do
658658

659659
defp do_expand_once({ :__ENV__, _, atom }, env) when is_atom(atom),
660660
do: { { :{}, [], tuple_to_list(env) }, true }
661-
defp do_expand_once({ { :., _, [{ :__ENV__, _, atom }, field] }, _, [] }, env) when is_atom(atom) and is_atom(field),
662-
do: { apply(env, field, []), true }
661+
defp do_expand_once({ { :., _, [{ :__ENV__, _, atom }, field] }, _, [] } = original, env) when
662+
is_atom(atom) and is_atom(field) do
663+
case :erlang.function_exported(Macro.Env, field, 1) do
664+
true -> { apply(env, field, []), true }
665+
false -> { original, false }
666+
end
667+
end
663668

664669
# Expand possible macro import invocation
665670
defp do_expand_once({ atom, meta, context } = original, env)

lib/elixir/src/elixir_code_server.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ start_link() ->
2727
gen_server:start_link({local, ?MODULE}, ?MODULE, ok, []).
2828

2929
init(ok) ->
30+
code:ensure_loaded('Elixir.Macro.Env'),
3031
code:ensure_loaded('Elixir.Module.LocalsTracker'),
3132
code:ensure_loaded('Elixir.Kernel.LexicalTracker'),
3233
{ ok, #elixir_code_server{} }.

lib/elixir/src/elixir_exp.erl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,12 @@ expand({ '__CALLER__', _, Atom } = Caller, E) when is_atom(Atom) ->
132132
expand({ '__ENV__', Meta, Atom }, E) when is_atom(Atom) ->
133133
Env = elixir_env:env_to_ex({ ?line(Meta), E }),
134134
{ { '{}', [], tuple_to_list(Env) }, E };
135-
expand({ { '.', _, [{ '__ENV__', Meta, Atom }, Field] }, _, [] }, E) when is_atom(Atom), is_atom(Field) ->
136-
{ (elixir_env:env_to_ex({ ?line(Meta), E })):Field(), E };
135+
expand({ { '.', DotMeta, [{ '__ENV__', Meta, Atom }, Field] }, CallMeta, [] }, E) when is_atom(Atom), is_atom(Field) ->
136+
Env = elixir_env:env_to_ex({ ?line(Meta), E }),
137+
case erlang:function_exported('Elixir.Macro.Env', Field, 1) of
138+
true -> { Env:Field(), E };
139+
false -> { { { '.', DotMeta, [{ '{}', [], tuple_to_list(Env) }, Field] }, CallMeta, [] }, E }
140+
end;
137141

138142
%% Quote
139143

lib/elixir/test/elixir/kernel/expansion_test.exs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ defmodule Kernel.ExpansionTest do
104104
end
105105

106106
test "__ENV__.accessor" do
107-
assert expand(quote(do: __ENV__.file)) == __ENV__.file
107+
env = __ENV__
108+
assert expand_env(quote(do: __ENV__.file), env) == { __ENV__.file, env }
109+
assert expand_env(quote(do: __ENV__.unknown), env) ==
110+
{ quote(do: unquote({ :{}, [], tuple_to_list(env.line(0)) }).unknown), env }
108111
end
109112

110113
## Super

lib/elixir/test/elixir/macro_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ defmodule MacroTest do
150150
assert Macro.expand_once(quote(do: :foo), __ENV__) == :foo
151151
end
152152

153+
test :expand_once_env do
154+
env = __ENV__
155+
assert Macro.expand_once(quote(do: __ENV__), env) == { :{}, [], tuple_to_list(env) }
156+
assert Macro.expand_once(quote(do: __ENV__.file), env) == env.file
157+
assert Macro.expand_once(quote(do: __ENV__.unkown), env) == quote(do: __ENV__.unkown)
158+
end
159+
153160
defmacro local_macro do
154161
:local_macro
155162
end

0 commit comments

Comments
 (0)