summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Leopardi <an.leopardi@gmail.com>2018-07-12 12:13:32 +0200
committerJosé Valim <jose.valim@gmail.com>2018-07-12 12:13:32 +0200
commit6023568bcfe48f74c8b1bca485f9f9c984ab0664 (patch)
tree3da72a8165ce1074221d87a8a0a0edc2e057e27c
parent35ac568044aca779d2c000f39cee974cae9cf0c0 (diff)
downloadelixir-6023568bcfe48f74c8b1bca485f9f9c984ab0664.tar.gz
Deprecate using non-empty lists with the Collectable protocol (#7785)
Closes #7421.
-rw-r--r--lib/eex/test/eex_test.exs2
-rw-r--r--lib/elixir/lib/collectable.ex10
-rw-r--r--lib/elixir/lib/enum.ex14
-rw-r--r--lib/elixir/test/elixir/enum_test.exs1
-rw-r--r--lib/ex_unit/lib/ex_unit/assertions.ex10
-rw-r--r--lib/mix/lib/mix/compilers/elixir.ex3
6 files changed, 29 insertions, 11 deletions
diff --git a/lib/eex/test/eex_test.exs b/lib/eex/test/eex_test.exs
index 805f4adb3..8a9439af3 100644
--- a/lib/eex/test/eex_test.exs
+++ b/lib/eex/test/eex_test.exs
@@ -519,7 +519,7 @@ defmodule EExTest do
end
defp assert_eval(expected, actual, binding \\ [], opts \\ []) do
- opts = Enum.into([file: __ENV__.file, engine: opts[:engine] || EEx.Engine], opts)
+ opts = Keyword.merge([file: __ENV__.file, engine: opts[:engine] || EEx.Engine], opts)
result = EEx.eval_string(actual, binding, opts)
assert result == expected
end
diff --git a/lib/elixir/lib/collectable.ex b/lib/elixir/lib/collectable.ex
index 495eb848c..075254e2a 100644
--- a/lib/elixir/lib/collectable.ex
+++ b/lib/elixir/lib/collectable.ex
@@ -79,6 +79,16 @@ end
defimpl Collectable, for: List do
def into(original) do
+ if original != [] do
+ IO.warn(
+ "the Collectable protocol is deprecated for non-empty lists. The behaviour of " <>
+ "things like Enum.into/2 or \"for\" comprehensions with an :into option is incorrect " <>
+ "when collecting into non-empty lists. If you're collecting into a non-empty keyword " <>
+ "list, consider using Keyword.merge/2 instead. If you're collecting into a non-empty " <>
+ "list, consider concatenating the two lists with the ++ operator."
+ )
+ end
+
fun = fn
list, {:cont, x} -> [x | list]
list, :done -> original ++ :lists.reverse(list)
diff --git a/lib/elixir/lib/enum.ex b/lib/elixir/lib/enum.ex
index 531896dbf..a1dbd921e 100644
--- a/lib/elixir/lib/enum.ex
+++ b/lib/elixir/lib/enum.ex
@@ -1164,10 +1164,14 @@ defmodule Enum do
@doc """
Inserts the given `enumerable` into a `collectable`.
+ Note that passing a non-empty list as the `collectable` is deprecated. If you're collecting
+ into a non-empty keyword list, consider using `Keyword.merge/2`. If you're collecting into a
+ non-empty list, consider something like `to_list(enumerable) ++ collectable`.
+
## Examples
- iex> Enum.into([1, 2], [0])
- [0, 1, 2]
+ iex> Enum.into([1, 2], [])
+ [1, 2]
iex> Enum.into([a: 1, b: 2], %{})
%{a: 1, b: 2}
@@ -1180,8 +1184,10 @@ defmodule Enum do
"""
@spec into(Enumerable.t(), Collectable.t()) :: Collectable.t()
- def into(enumerable, collectable) when is_list(collectable) do
- collectable ++ to_list(enumerable)
+ def into(enumerable, collectable)
+
+ def into(enumerable, []) do
+ to_list(enumerable)
end
def into(%_{} = enumerable, collectable) do
diff --git a/lib/elixir/test/elixir/enum_test.exs b/lib/elixir/test/elixir/enum_test.exs
index 4df60680f..f9a625e21 100644
--- a/lib/elixir/test/elixir/enum_test.exs
+++ b/lib/elixir/test/elixir/enum_test.exs
@@ -1098,7 +1098,6 @@ defmodule EnumTest.Range do
end
test "into/2" do
- assert Enum.into(3..5, [1, 2]) == [1, 2, 3, 4, 5]
assert Enum.into(1..5, []) == [1, 2, 3, 4, 5]
end
diff --git a/lib/ex_unit/lib/ex_unit/assertions.ex b/lib/ex_unit/lib/ex_unit/assertions.ex
index f8c46ada9..f1e5300da 100644
--- a/lib/ex_unit/lib/ex_unit/assertions.ex
+++ b/lib/ex_unit/lib/ex_unit/assertions.ex
@@ -584,10 +584,12 @@ defmodule ExUnit.Assertions do
defp collect_vars_from_pattern({:when, _, [left, right]}) do
pattern = collect_vars_from_pattern(left)
- for {name, _, context} = var <- collect_vars_from_pattern(right),
- Enum.any?(pattern, &match?({^name, _, ^context}, &1)),
- into: pattern,
- do: var
+ vars =
+ for {name, _, context} = var <- collect_vars_from_pattern(right),
+ Enum.any?(pattern, &match?({^name, _, ^context}, &1)),
+ do: var
+
+ pattern ++ vars
end
defp collect_vars_from_pattern(expr) do
diff --git a/lib/mix/lib/mix/compilers/elixir.ex b/lib/mix/lib/mix/compilers/elixir.ex
index 3ea777538..f18605368 100644
--- a/lib/mix/lib/mix/compilers/elixir.ex
+++ b/lib/mix/lib/mix/compilers/elixir.ex
@@ -82,9 +82,10 @@ defmodule Mix.Compilers.Elixir do
{last_mtime, last_size} = Map.fetch!(sources_stats, source),
times = Enum.map(external, &(sources_stats |> Map.fetch!(&1) |> elem(0))),
size != last_size or Mix.Utils.stale?([last_mtime | times], [modified]),
- into: new_paths,
do: source
+ changed = new_paths ++ changed
+
stale_local_deps = stale_local_deps(manifest, modified)
{modules, structs, changed} =