diff --git a/lib/elixir/src/elixir_expand.erl b/lib/elixir/src/elixir_expand.erl index 97e72d52da8..e52bceb3827 100644 --- a/lib/elixir/src/elixir_expand.erl +++ b/lib/elixir/src/elixir_expand.erl @@ -266,6 +266,9 @@ expand({quote, Meta, [Opts, Do]}, S, E) when is_list(Do) -> Unquote = proplists:get_value(unquote, EOpts, DefaultUnquote), Generated = proplists:get_value(generated, EOpts, false), + (map_get(context, E) /= nil) andalso Unquote andalso elixir_quote:has_unquotes(Exprs) andalso + file_error(Meta, E, ?MODULE, quote_in_pattern_with_unquote), + {Q, QContext, QPrelude} = elixir_quote:build(Meta, Line, File, Context, Unquote, Generated, ET), {EPrelude, SP, EP} = expand(QPrelude, ST, ET), {EContext, SC, EC} = expand(QContext, SP, EP), @@ -1216,6 +1219,8 @@ format_error({expected_compile_time_module, Kind, GivenTerm}) -> format_error({unquote_outside_quote, Unquote}) -> %% Unquote can be "unquote" or "unquote_splicing". io_lib:format("~p called outside quote", [Unquote]); +format_error(quote_in_pattern_with_unquote) -> + "unquote is not allowed when quote is used inside a pattern or guard"; format_error({invalid_bind_quoted_for_quote, BQ}) -> io_lib:format("invalid :bind_quoted for quote, expected a keyword list of variable names, got: ~ts", ['Elixir.Macro':to_string(BQ)]); diff --git a/lib/elixir/test/elixir/kernel/errors_test.exs b/lib/elixir/test/elixir/kernel/errors_test.exs index 2c1dc605ae7..06d1ed68e03 100644 --- a/lib/elixir/test/elixir/kernel/errors_test.exs +++ b/lib/elixir/test/elixir/kernel/errors_test.exs @@ -456,6 +456,21 @@ defmodule Kernel.ErrorsTest do """ end + test "invalid unquote when quote/1 is in a pattern" do + assert_compile_error( + ["unquote is not allowed when quote is used inside a pattern or guard"], + ~c""" + defmodule Kernel.ErrorsTest.InvalidUnquoteInQuotePattern do + def my_fun(ast) do + case ast do + quote(do: foo(unquote(x))) -> x + end + end + end + """ + ) + end + test "invalid attribute" do msg = ~r"cannot inject attribute @foo into function/macro because cannot escape "