Skip to content

Commit 9897b89

Browse files
author
José Valim
committed
Deprecate x in y inside matches
1 parent 90af53c commit 9897b89

File tree

11 files changed

+49
-71
lines changed

11 files changed

+49
-71
lines changed

lib/elixir/lib/file.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ defmodule File do
481481
case F.list_dir(src) do
482482
{ :ok, files } ->
483483
case mkdir(dest) do
484-
success in [:ok, { :error, :eexist }] ->
484+
success when success in [:ok, { :error, :eexist }] ->
485485
Enum.reduce(files, [dest|acc], fn(x, acc) ->
486486
do_cp_r(FN.join(src, x), FN.join(dest, x), callback, acc)
487487
end)

lib/elixir/lib/kernel.ex

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,8 +2636,8 @@ defmodule Kernel do
26362636

26372637
quote do
26382638
case unquote(condition) do
2639-
_ in [false, nil] -> unquote(else_clause)
2640-
_ -> unquote(do_clause)
2639+
unquote(cond_var) when unquote(cond_var) in [false, nil] -> unquote(else_clause)
2640+
_ -> unquote(do_clause)
26412641
end
26422642
end
26432643
end
@@ -2987,8 +2987,8 @@ defmodule Kernel do
29872987
defmacro left && right do
29882988
quote do
29892989
case unquote(left) do
2990-
var!(andand, false) in [false, nil] ->
2991-
var!(andand, false)
2990+
unquote(temp_var) when unquote(temp_var) in [false, nil] ->
2991+
unquote(temp_var)
29922992
_ ->
29932993
unquote(right)
29942994
end
@@ -3018,10 +3018,10 @@ defmodule Kernel do
30183018
defmacro left || right do
30193019
quote do
30203020
case unquote(left) do
3021-
var!(oror, false) in [false, nil] ->
3021+
unquote(temp_var) when unquote(temp_var) in [false, nil] ->
30223022
unquote(right)
3023-
var!(oror, false) ->
3024-
var!(oror, false)
3023+
unquote(temp_var) ->
3024+
unquote(temp_var)
30253025
end
30263026
end
30273027
end
@@ -3619,13 +3619,26 @@ defmodule Kernel do
36193619
defp expand_compact([]), do: []
36203620

36213621
defp falsy_clause(meta, acc) do
3622-
{ [quote(do: _ in [false, nil])], meta, acc }
3622+
{ [quote(do: unquote(cond_var) when unquote(cond_var) in [false, nil])], meta, acc }
36233623
end
36243624

36253625
defp truthy_clause(meta, clause) do
36263626
{ [quote(do: _)], meta, clause }
36273627
end
36283628

3629+
# Setting cond: true in metadata turns on a small optimization
3630+
# in Elixir compiler. In the long run, we want to bring this
3631+
# optimization to Elixir land, but not right now.
3632+
defp cond_var do
3633+
{ :x, [cond: true, temp: true], Kernel }
3634+
end
3635+
3636+
# A temporary var only lasts its current clause, never leak
3637+
# into other clauses.
3638+
defp temp_var do
3639+
{ :x, [temp: true], Kernel }
3640+
end
3641+
36293642
defp get_line(meta) do
36303643
case :lists.keyfind(:line, 1, meta) do
36313644
{ :line, line } -> line

lib/elixir/lib/kernel/parallel_compiler.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ defmodule Kernel.ParallelCompiler do
4848
result = spawn_compilers(files, files, path, callbacks, [], [], schedulers, [])
4949

5050
# In case --warning-as-errors is enabled and there was a warning,
51-
# compilation status will be set to error and we fail with Kernel.CompilationError
51+
# compilation status will be set to error and we fail with CompileError
5252
case :elixir_code_server.call(:compilation_status) do
5353
:ok -> result
5454
:error -> raise CompileError, [], []

lib/elixir/lib/kernel/special_forms.ex

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -855,10 +855,6 @@ defmodule Kernel.SpecialForms do
855855

856856
@doc """
857857
Defines a variable in the given context.
858-
859-
If the context is `false`, it is not stored in any particular
860-
context and the variable is not shared in between clauses.
861-
862858
Check `quote/2` for more information.
863859
"""
864860
defmacro var!(var, context)

lib/elixir/src/elixir_macros.erl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ translate({ in, Meta, [Left, Right] }, #elixir_scope{extra_guards=nil} = S) ->
4444
{ TExpr, TS };
4545

4646
translate({ in, Meta, [Left, Right] }, #elixir_scope{extra_guards=Extra} = S) ->
47+
elixir_errors:deprecation(Meta, S#elixir_scope.file, "in operator inside matches is deprecated, please move it to a guard"),
4748
{ TVar, TExpr, TS } = translate_in(Meta, Left, Right, S),
4849
{ TVar, TS#elixir_scope{extra_guards=[TExpr|Extra]} };
4950

@@ -281,8 +282,18 @@ decreasing_compare(Line, Var, Start, End) ->
281282
{ op, Line, '=<', Var, Start },
282283
{ op, Line, '>=', Var, End } }.
283284

284-
rewrite_case_clauses([{do,Meta1,[{in,_,[{'_',_,_},[false,nil]]}],False},{do,Meta2,[{'_',_,_}],True}]) ->
285-
[{do,Meta1,[false],False},{do,Meta2,[true],True}];
285+
%% TODO: Once we have elixir_exp, we can move this
286+
%% clause to Elixir code and out of case.
287+
rewrite_case_clauses([
288+
{do,Meta1,[{'when',_,[{V,M,C},{in,_,[{V,M,C},[false,nil]]}]}],False},
289+
{do,Meta2,[{'_',_,UC}],True}] = Clauses)
290+
when is_atom(V), is_list(M), is_atom(C), is_atom(UC) ->
291+
case lists:keyfind('cond', 1, M) of
292+
{ 'cond', true } ->
293+
[{do,Meta1,[false],False},{do,Meta2,[true],True}];
294+
_ ->
295+
Clauses
296+
end;
286297

287298
rewrite_case_clauses(Clauses) ->
288299
Clauses.

lib/elixir/src/elixir_scope.erl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
translate_var(Meta, Name, Kind, S, Callback) when is_atom(Kind); is_integer(Kind) ->
1414
Line = ?line(Meta),
1515
Vars = S#elixir_scope.vars,
16+
Temp = lists:keyfind(temp, 1, Meta) == { temp, true },
1617
Tuple = { Name, Kind },
1718

1819
case Name of
@@ -41,7 +42,7 @@ translate_var(Meta, Name, Kind, S, Callback) when is_atom(Kind); is_integer(Kind
4142
true -> ordsets:add_element(Tuple, TempVars)
4243
end,
4344
clause_vars=if
44-
ClauseVars == nil; Kind == false -> ClauseVars;
45+
ClauseVars == nil; Temp == true -> ClauseVars;
4546
true -> orddict:store(Tuple, RealName, ClauseVars)
4647
end
4748
} }

lib/elixir/test/elixir/kernel/case_test.exs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,13 @@ defmodule Kernel.CaseTest do
3030
end) == :done
3131
end
3232

33-
test :match_with_in do
34-
assert(case 3 do
35-
x in [1, 2, 3] ->
36-
true
37-
end)
38-
39-
assert(case { 3, 3 } do
40-
{ x in [1, 2, 3], y } when y == 2 ->
41-
false
42-
{ x in [1, 2, 3], y } when y == 1 when y == 3 ->
43-
true
44-
end)
45-
end
46-
4733
test :in_operator_outside_case do
4834
x = 1
4935
y = 4
5036
assert x in [1, 2, 3], "in assertion"
5137
assert not y in [1, 2, 3], "not in assertion"
5238
end
5339

54-
test :in_operator_in_function_definition do
55-
assert with_in(3, :it_works) == :it_works
56-
assert with_in(3, "it fails") == false
57-
assert with_in(0, :it_fails) == false
58-
end
59-
6040
defp get_case do
6141
case internal do
6242
:invalid ->
@@ -93,7 +73,4 @@ defmodule Kernel.CaseTest do
9373
end
9474
{x, vx}
9575
end
96-
97-
defp with_in(x in [1, 2, 3], other) when is_atom(other), do: other
98-
defp with_in(_, _), do: false
9976
end

lib/elixir/test/elixir/kernel/def_clauses_test.exs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,6 @@ defmodule Kernel.ClausesTest do
2323
def bar, do: 1
2424
defclause foo(1), do: 2
2525

26-
test :in_operator_in_function_definition do
27-
assert with_in(3, :it_works) == :it_works
28-
assert with_in(3, "it fails") == false
29-
assert with_in(0, :it_fails) == false
30-
end
31-
32-
defp with_in(x in [1, 2, 3], other) when is_atom(other), do: other
33-
defp with_in(_, _), do: false
34-
3526
test :clauses_without_implementation_can_have_default_args do
3627
assert a_number == 13
3728
assert a_number(4) == 17

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

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -180,22 +180,8 @@ defmodule Kernel.WarningTest do
180180
end
181181
"""
182182
end) =~ "nofile:6: this clause cannot match because a previous clause at line 5 always matches"
183-
184-
assert capture_err(fn ->
185-
Code.eval_string """
186-
defmodule Sample3 do
187-
def is_binary_cond_case do
188-
v = "bc"
189-
case(is_binary(v)) do
190-
_ in [false, nil] -> :ok
191-
_ -> :bin
192-
end
193-
end
194-
end
195-
"""
196-
end) =~ "nofile:5: this clause cannot match because a previous clause at line 6 always matches"
197183
after
198-
purge [Sample1, Sample2, Sample3]
184+
purge [Sample1, Sample2]
199185
end
200186

201187
test :unused_docs do

lib/elixir/test/elixir/macro_test.exs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,19 +157,21 @@ defmodule MacroTest do
157157
end
158158

159159
test :expand_once_with_imported_macro do
160+
temp_var = { :x, [temp: true], Kernel }
160161
assert Macro.expand_once(quote(do: 1 || false), __ENV__) == (quote context: Kernel do
161162
case 1 do
162-
var!(oror, false) in [false, nil] -> false
163-
var!(oror, false) -> var!(oror, false)
163+
unquote(temp_var) when unquote(temp_var) in [false, nil] -> false
164+
unquote(temp_var) -> unquote(temp_var)
164165
end
165166
end)
166167
end
167168

168169
test :expand_once_with_require_macro do
170+
temp_var = { :x, [temp: true], Kernel }
169171
assert Macro.expand_once(quote(do: Kernel.||(1, false)), __ENV__) == (quote context: Kernel do
170172
case 1 do
171-
var!(oror, false) in [false, nil] -> false
172-
var!(oror, false) -> var!(oror, false)
173+
unquote(temp_var) when unquote(temp_var) in [false, nil] -> false
174+
unquote(temp_var) -> unquote(temp_var)
173175
end
174176
end)
175177
end
@@ -187,10 +189,11 @@ defmodule MacroTest do
187189
end
188190

189191
test :expand do
192+
temp_var = { :x, [temp: true], Kernel }
190193
assert Macro.expand(quote(do: oror(1, false)), __ENV__) == (quote context: Kernel do
191194
case 1 do
192-
var!(oror, false) in [false, nil] -> false
193-
var!(oror, false) -> var!(oror, false)
195+
unquote(temp_var) when unquote(temp_var) in [false, nil] -> false
196+
unquote(temp_var) -> unquote(temp_var)
194197
end
195198
end)
196199
end

0 commit comments

Comments
 (0)