Skip to content

Commit bff9f3e

Browse files
committed
Point out module must be required before macro usage in match/guard
1 parent ff4adca commit bff9f3e

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

lib/elixir/src/elixir_rewrite.erl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,15 +355,23 @@ allowed_guard(Right, Arity) ->
355355
erl_internal:guard_bif(Right, Arity) orelse elixir_utils:guard_op(Right, Arity).
356356

357357
format_error({invalid_guard, Receiver, Right, Arity, Context}) ->
358-
io_lib:format("cannot invoke remote function ~ts.~ts/~B inside a ~ts",
358+
io_lib:format(cannot_invoke_or_maybe_require(Receiver, Right, Arity) ++ " ~ts.~ts/~B inside a ~ts",
359359
['Elixir.Macro':to_string(Receiver), Right, Arity, Context]);
360360
format_error({invalid_match, Receiver, Right, Arity}) ->
361-
io_lib:format("cannot invoke remote function ~ts.~ts/~B inside a match",
361+
io_lib:format(cannot_invoke_or_maybe_require(Receiver, Right, Arity) ++ " ~ts.~ts/~B inside a match",
362362
['Elixir.Macro':to_string(Receiver), Right, Arity]);
363363
format_error({invalid_match_append, Arg}) ->
364364
io_lib:format("invalid argument for ++ operator inside a match, expected a literal proper list, got: ~ts",
365365
['Elixir.Macro':to_string(Arg)]).
366366

367+
cannot_invoke_or_maybe_require(Receiver, Fun, Arity) ->
368+
try
369+
true = lists:member({Fun, Arity}, Receiver:'__info__'(macros)),
370+
["you must require the module", 'Elixir.Macro':to_string(Receiver), " before invoking macro"]
371+
catch
372+
_:_ -> "cannot invoke remote function"
373+
end.
374+
367375
is_always_string({{'.', _, [Module, Function]}, _, Args}) ->
368376
is_always_string(Module, Function, length(Args));
369377
is_always_string(Ast) ->

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,15 @@ defmodule Kernel.ExpansionTest do
806806
end)
807807
end
808808

809+
test "in guards with macros" do
810+
message =
811+
~r"you must require the moduleInteger before invoking macro Integer.is_even/1 inside a guard"
812+
813+
assert_compile_error(message, fn ->
814+
expand(quote(do: fn arg when Integer.is_even(arg) -> arg end))
815+
end)
816+
end
817+
809818
test "in guards with bitstrings" do
810819
message = ~r"cannot invoke remote function String.Chars.to_string/1 inside a guard"
811820

0 commit comments

Comments
 (0)