Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/elixir/lib/kernel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5220,6 +5220,11 @@ defmodule Kernel do
end
end

defmacro defmodule(alias, [{:do, _block}, {atom, _} | _]) when is_atom(atom) do
raise ArgumentError,
"unexpected reserved word at the top-level of the \"defmodule #{Macro.to_string(alias)}\" do-block: #{atom}"
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also have a catch-all? raise "expected do-block in defmodule, got: #{inspect(other)}" ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't so sure in the absence of a concrete example (maybe can happen with metaprogramming?), how much it would be more helpful since we'll end up emitting the AST anyway.
In the case of catch etc, we know exactly what the AST looks like, and the message is an improvement over the clause error.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always add it later, so ship it!


defp module_meta({_, meta, _}), do: meta
defp module_meta(_), do: []

Expand Down
12 changes: 12 additions & 0 deletions lib/elixir/test/elixir/kernel/errors_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,18 @@ defmodule Kernel.ErrorsTest do
)
end

test "reserved word used at module top-level" do
assert_eval_raise(
ArgumentError,
["unexpected reserved word at the top-level of the \"defmodule Foo\" do-block: catch"],
"""
defmodule Foo do
def foo, do: :foo catch :bar
end
"""
)
end

defp bad_remote_call(x), do: x.foo()

defmacro sample(0), do: 0
Expand Down
Loading