diff options
author | Andrea Leopardi <an.leopardi@gmail.com> | 2018-07-12 12:13:32 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2018-07-12 12:13:32 +0200 |
commit | 6023568bcfe48f74c8b1bca485f9f9c984ab0664 (patch) | |
tree | 3da72a8165ce1074221d87a8a0a0edc2e057e27c | |
parent | 35ac568044aca779d2c000f39cee974cae9cf0c0 (diff) | |
download | elixir-6023568bcfe48f74c8b1bca485f9f9c984ab0664.tar.gz |
Deprecate using non-empty lists with the Collectable protocol (#7785)
Closes #7421.
-rw-r--r-- | lib/eex/test/eex_test.exs | 2 | ||||
-rw-r--r-- | lib/elixir/lib/collectable.ex | 10 | ||||
-rw-r--r-- | lib/elixir/lib/enum.ex | 14 | ||||
-rw-r--r-- | lib/elixir/test/elixir/enum_test.exs | 1 | ||||
-rw-r--r-- | lib/ex_unit/lib/ex_unit/assertions.ex | 10 | ||||
-rw-r--r-- | lib/mix/lib/mix/compilers/elixir.ex | 3 |
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} = |