Skip to content

Commit c7f78e8

Browse files
committed
Emit warnings for duplicate patterns instead of errors
1 parent 6a24baf commit c7f78e8

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

lib/elixir/src/elixir_clauses.erl

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
parallel_match(Meta, Expr, S, #{context := match} = E) ->
1313
#elixir_ex{vars={_Read, Write}} = S,
14-
Matches = unpack_match(Expr, Meta, []),
14+
Matches = unpack_match(Expr, Meta, [], E),
1515

1616
{[{_, EHead} | ETail], EWrites, SM, EM} =
1717
lists:foldl(fun({EMeta, Match}, {AccMatches, AccWrites, SI, EI}) ->
@@ -31,9 +31,13 @@ parallel_match(Meta, Expr, S, #{context := match} = E) ->
3131
VWrite = (Write /= false) andalso elixir_env:merge_vars(Write, PWrites),
3232
{EMatch, SM#elixir_ex{vars={VRead, VWrite}, prematch={PRead, PCycles, PInfo}}, EM}.
3333

34-
unpack_match({'=', Meta, [Left, Right]}, _Meta, Acc) ->
35-
unpack_match(Left, Meta, unpack_match(Right, Meta, Acc));
36-
unpack_match(Node, Meta, Acc) ->
34+
unpack_match({'=', Meta, [{_, VarMeta, _} = Node, Node]}, _Meta, Acc, E) ->
35+
%% TODO: remove this clause on Elixir v1.23
36+
file_warn(VarMeta, ?key(E, file), ?MODULE, {duplicate_match, Node}),
37+
unpack_match(Node, Meta, Acc, E);
38+
unpack_match({'=', Meta, [Left, Right]}, _Meta, Acc, E) ->
39+
unpack_match(Left, Meta, unpack_match(Right, Meta, Acc, E), E);
40+
unpack_match(Node, Meta, Acc, _E) ->
3741
[{Meta, Node} | Acc].
3842

3943
store_cycles([Write | Writes], {Cycles, SkipList}, Acc) ->
@@ -532,6 +536,13 @@ origin(Meta, Default) ->
532536
false -> Default
533537
end.
534538

539+
format_error({duplicate_match, Expr}) ->
540+
String = 'Elixir.Macro':to_string(Expr),
541+
io_lib:format(
542+
"this pattern is matched against itself inside a match: ~ts = ~ts",
543+
[String, String]
544+
);
545+
535546
format_error({recursive, Vars, TypeExpr}) ->
536547
Code =
537548
case TypeExpr of

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,6 @@ defmodule Kernel.ExpansionTest do
190190
end
191191

192192
test "errors on directly recursive definitions" do
193-
assert_compile_error(
194-
~r"""
195-
recursive variable definition in patterns:
196-
197-
x = x
198-
199-
the variable "x" \(context Kernel.ExpansionTest\) is defined in function of itself
200-
""",
201-
fn -> expand(quote(do: (x = x) = :ok)) end
202-
)
203-
204193
assert_compile_error(
205194
~r"""
206195
recursive variable definition in patterns:

lib/elixir/test/elixir/kernel/warning_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,20 @@ defmodule Kernel.WarningTest do
264264
purge(Sample)
265265
end
266266

267+
test "duplicate pattern" do
268+
output =
269+
capture_eval("""
270+
defmodule Sample do
271+
var = quote(do: x)
272+
def hello(unquote(var) = unquote(var)), do: unquote(var)
273+
end
274+
""")
275+
276+
assert output =~ "this pattern is matched against itself inside a match: x = x"
277+
after
278+
purge(Sample)
279+
end
280+
267281
test "unused compiler variable" do
268282
output =
269283
capture_eval("""

0 commit comments

Comments
 (0)