Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package elixir for openSUSE:Factory checked in at 2021-07-13 22:37:39 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/elixir (Old) and /work/SRC/openSUSE:Factory/.elixir.new.2625 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "elixir" Tue Jul 13 22:37:39 2021 rev:17 rq:906080 version:1.12.2 Changes: -------- --- /work/SRC/openSUSE:Factory/elixir/elixir.changes 2021-06-14 23:11:54.500839659 +0200 +++ /work/SRC/openSUSE:Factory/.elixir.new.2625/elixir.changes 2021-07-13 22:38:03.413828136 +0200 @@ -1,0 +2,22 @@ +Mon Jul 12 07:26:51 UTC 2021 - Sven Marquardt <dev@mail.smarquardt.space> + +- Elixir 1.12.2 + + * Bug fixes + Elixir + [Kernel] Ensure deprecated macros emit warnings + + Mix + [mix deps] Ensure unconstrained rebar deps generate valid mix specifications + + * Enhancements + Elixir + [elixirc] Change the output of `--profile time` to make it easier to detect outliers + [Application] Do not add compile time deps on args to `Application.compile_env/2` and `Application.compile_env!/2` + [Enum] Optimize `Enum.into/3` and `Map.new/2` + + Mix + [mix compile] Compile most recently changed files first + [mix compile, mix run, mix test] Speed up the time taken to load dependencies. This should make the usage of Mix inside projects quite more responsive + +------------------------------------------------------------------- Old: ---- elixir-1.12.1.tar.gz New: ---- elixir-1.12.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ elixir-doc.spec ++++++ --- /var/tmp/diff_new_pack.b4JWQW/_old 2021-07-13 22:38:03.789825109 +0200 +++ /var/tmp/diff_new_pack.b4JWQW/_new 2021-07-13 22:38:03.793825076 +0200 @@ -17,7 +17,7 @@ Name: elixir-doc -Version: 1.12.1 +Version: 1.12.2 Release: 0 Summary: Documentation for elixir License: Apache-2.0 elixir.spec: same change ++++++ elixir-1.12.1.tar.gz -> elixir-1.12.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/CHANGELOG.md new/elixir-1.12.2/CHANGELOG.md --- old/elixir-1.12.1/CHANGELOG.md 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/CHANGELOG.md 2021-07-01 18:15:34.000000000 +0200 @@ -90,6 +90,31 @@ Elixir v1.12 has the additional of many functions across the standard library. The `Enum` module received additions such as `Enum.count_until/2`, `Enum.product/1`, `Enum.zip_with/2`, and more. The `Integer` module now includes `Integer.pow/2` and `Integer.extended_gcd/2`. Finally, the `Kernel` module got two new functions, `Kernel.then/2` and `Kernel.tap/2`, which are specially useful in `|>` pipelines. +## v1.12.2 (2021-07-01) + +### 1. Bug fixes + +#### Elixir + + * [Kernel] Ensure deprecated macros emit warnings + +#### Mix + + * [mix deps] Ensure unconstrained rebar deps generate valid mix specifications + +### 2. Enhancements + +#### Elixir + + * [elixirc] Change the output of `--profile time` to make it easier to detect outliers + * [Application] Do not add compile time deps on args to `Application.compile_env/2` and `Application.compile_env!/2` + * [Enum] Optimize `Enum.into/3` and `Map.new/2` + +#### Mix + + * [mix compile] Compile most recently changed files first + * [mix compile, mix run, mix test] Speed up the time taken to load dependencies. This should make the usage of Mix inside projects quite more responsive + ## v1.12.1 (2021-05-28) ### 1. Bug fixes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/VERSION new/elixir-1.12.2/VERSION --- old/elixir-1.12.1/VERSION 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/VERSION 2021-07-01 18:15:34.000000000 +0200 @@ -1 +1 @@ -1.12.1 \ No newline at end of file +1.12.2 \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/application.ex new/elixir-1.12.2/lib/elixir/lib/application.ex --- old/elixir-1.12.1/lib/elixir/lib/application.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/application.ex 2021-07-01 18:15:34.000000000 +0200 @@ -507,11 +507,22 @@ raise "Application.compile_env/3 cannot be called inside functions, only in the module body" end + key_or_path = expand_key_or_path(key_or_path, __CALLER__) + quote do Application.__compile_env__(unquote(app), unquote(key_or_path), unquote(default), __ENV__) end end + defp expand_key_or_path({:__aliases__, _, _} = alias, env), + do: Macro.expand(alias, %{env | function: {:__info__, 1}}) + + defp expand_key_or_path(list, env) when is_list(list), + do: Enum.map(list, &expand_key_or_path(&1, env)) + + defp expand_key_or_path(other, _env), + do: other + @doc false def __compile_env__(app, key_or_path, default, env) do case fetch_compile_env(app, key_or_path, env) do @@ -533,6 +544,8 @@ raise "Application.compile_env!/2 cannot be called inside functions, only in the module body" end + key_or_path = expand_key_or_path(key_or_path, __CALLER__) + quote do Application.__compile_env__!(unquote(app), unquote(key_or_path), __ENV__) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/code.ex new/elixir-1.12.2/lib/elixir/lib/code.ex --- old/elixir-1.12.1/lib/elixir/lib/code.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/code.ex 2021-07-01 18:15:34.000000000 +0200 @@ -1550,6 +1550,7 @@ @doc """ Same as `ensure_loaded/1` but raises if the module cannot be loaded. """ + @doc since: "1.12.0" @spec ensure_loaded!(module) :: module def ensure_loaded!(module) do case ensure_loaded(module) do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/enum.ex new/elixir-1.12.2/lib/elixir/lib/enum.ex --- old/elixir-1.12.1/lib/elixir/lib/enum.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/enum.ex 2021-07-01 18:15:34.000000000 +0200 @@ -1421,28 +1421,35 @@ into_protocol(enumerable, collectable) end - def into(%{} = enumerable, %{} = collectable) do - Map.merge(collectable, enumerable) - end - - def into(enumerable, %{} = collectable) when is_list(enumerable) do - Map.merge(collectable, :maps.from_list(enumerable)) - end - def into(enumerable, %{} = collectable) do - reduce(enumerable, collectable, fn {key, val}, acc -> - Map.put(acc, key, val) - end) + if map_size(collectable) == 0 do + into_map(enumerable) + else + into_map(enumerable, collectable) + end end def into(enumerable, collectable) do into_protocol(enumerable, collectable) end + defp into_map(%{} = enumerable), do: enumerable + defp into_map(enumerable) when is_list(enumerable), do: :maps.from_list(enumerable) + defp into_map(enumerable), do: enumerable |> Enum.to_list() |> :maps.from_list() + + defp into_map(%{} = enumerable, collectable), + do: Map.merge(collectable, enumerable) + + defp into_map(enumerable, collectable) when is_list(enumerable), + do: Map.merge(collectable, :maps.from_list(enumerable)) + + defp into_map(enumerable, collectable), + do: Enum.reduce(enumerable, collectable, fn {key, val}, acc -> Map.put(acc, key, val) end) + defp into_protocol(enumerable, collectable) do {initial, fun} = Collectable.into(collectable) - into(enumerable, initial, fun, fn entry, acc -> + into_protocol(enumerable, initial, fun, fn entry, acc -> fun.(acc, {:cont, entry}) end) end @@ -1461,20 +1468,42 @@ """ @spec into(Enumerable.t(), Collectable.t(), (term -> term)) :: Collectable.t() - def into(enumerable, collectable, transform) when is_list(collectable) do collectable ++ map(enumerable, transform) end + def into(%_{} = enumerable, collectable, transform) do + into_protocol(enumerable, collectable, transform) + end + + def into(enumerable, %_{} = collectable, transform) do + into_protocol(enumerable, collectable, transform) + end + + def into(enumerable, %{} = collectable, transform) do + if map_size(collectable) == 0 do + enumerable |> Enum.map(transform) |> :maps.from_list() + else + Enum.reduce(enumerable, collectable, fn entry, acc -> + {key, val} = transform.(entry) + Map.put(acc, key, val) + end) + end + end + def into(enumerable, collectable, transform) do + into_protocol(enumerable, collectable, transform) + end + + defp into_protocol(enumerable, collectable, transform) do {initial, fun} = Collectable.into(collectable) - into(enumerable, initial, fun, fn entry, acc -> + into_protocol(enumerable, initial, fun, fn entry, acc -> fun.(acc, {:cont, transform.(entry)}) end) end - defp into(enumerable, initial, fun, callback) do + defp into_protocol(enumerable, initial, fun, callback) do try do reduce(enumerable, initial, callback) catch diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/io.ex new/elixir-1.12.2/lib/elixir/lib/io.ex --- old/elixir-1.12.1/lib/elixir/lib/io.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/io.ex 2021-07-01 18:15:34.000000000 +0200 @@ -516,6 +516,7 @@ IO.stream(:stdio, :line) """ + @doc since: "1.12.0" def stream, do: stream(:stdio, :line) @doc """ @@ -534,6 +535,9 @@ Note that an IO stream has side effects and every time you go over the stream you may get different results. + `stream/1` has been introduced in Elixir v1.12.0, + while `stream/2` has been available since v1.0.0. + ## Examples Here is an example on how we mimic an echo server @@ -557,6 +561,7 @@ IO.binstream(:stdio, :line) """ + @doc since: "1.12.0" def binstream, do: binstream(:stdio, :line) @doc """ @@ -574,6 +579,9 @@ Finally, do not use this function on IO devices in Unicode mode as it will return the wrong result. + + `binstream/1` has been introduced in Elixir v1.12.0, + while `binstream/2` has been available since v1.0.0. """ @spec binstream(device, :line | pos_integer) :: Enumerable.t() def binstream(device \\ :stdio, line_or_bytes) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/kernel/parallel_compiler.ex new/elixir-1.12.2/lib/elixir/lib/kernel/parallel_compiler.ex --- old/elixir-1.12.1/lib/elixir/lib/kernel/parallel_compiler.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/kernel/parallel_compiler.ex 2021-07-01 18:15:34.000000000 +0200 @@ -623,13 +623,13 @@ data = maybe_warn_long_compilation(data, state) if state.profile != :none do - compiling = System.convert_time_unit(data.compiling, :native, :millisecond) - waiting = System.convert_time_unit(data.waiting, :native, :millisecond) - extra = if waiting > 0, do: " (plus #{waiting}ms waiting)", else: "" + compiling = to_padded_ms(data.compiling) + waiting = to_padded_ms(data.waiting) + relative = Path.relative_to_cwd(data.file) IO.puts( :stderr, - "[profile] #{Path.relative_to_cwd(data.file)} compiled in #{compiling}ms" <> extra + "[profile] #{compiling}ms compiling + #{waiting}ms waiting for #{relative}" ) end @@ -640,6 +640,13 @@ end) end + defp to_padded_ms(time) do + time + |> System.convert_time_unit(:native, :millisecond) + |> Integer.to_string() + |> String.pad_leading(6, " ") + end + defp discard_down(pid) do receive do {:DOWN, _, :process, ^pid, _} -> :ok diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/kernel.ex new/elixir-1.12.2/lib/elixir/lib/kernel.ex --- old/elixir-1.12.1/lib/elixir/lib/kernel.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/kernel.ex 2021-07-01 18:15:34.000000000 +0200 @@ -5554,7 +5554,7 @@ quote(do: List.to_charlist(unquote(unescape_list_tokens(pieces)))) end - @doc """ + @doc ~S""" Handles the sigil `~r` for regular expressions. It returns a regular expression pattern, unescaping characters and replacing @@ -5564,12 +5564,15 @@ ## Examples - iex> Regex.match?(~r(foo), "foo") + iex> Regex.match?(~r/foo/, "foo") true iex> Regex.match?(~r/a#{:b}c/, "abc") true + While the `~r` sigil allows parens and brackets to be used as delimiters, + it is preferred to use `"` or `/` to avoid escaping conflicts with reserved + regex characters. """ defmacro sigil_r(term, modifiers) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/macro/env.ex new/elixir-1.12.2/lib/elixir/lib/macro/env.ex --- old/elixir-1.12.1/lib/elixir/lib/macro/env.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/macro/env.ex 2021-07-01 18:15:34.000000000 +0200 @@ -105,7 +105,9 @@ vars: vars } + # Define the __struct__ callbacks by hand for bootstrap reasons. # TODO: Remove :vars field on v2.0 + @doc false def __struct__ do %{ __struct__: __MODULE__, @@ -130,6 +132,7 @@ } end + @doc false def __struct__(kv) do Enum.reduce(kv, __struct__(), fn {k, v}, acc -> :maps.update(k, v, acc) end) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/lib/map.ex new/elixir-1.12.2/lib/elixir/lib/map.ex --- old/elixir-1.12.1/lib/elixir/lib/map.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/lib/map.ex 2021-07-01 18:15:34.000000000 +0200 @@ -216,20 +216,10 @@ @spec new(Enumerable.t(), (term -> {key, value})) :: map def new(enumerable, transform) when is_function(transform, 1) do enumerable - |> Enum.to_list() - |> new_transform(transform, []) - end - - defp new_transform([], _fun, acc) do - acc - |> :lists.reverse() + |> Enum.map(transform) |> :maps.from_list() end - defp new_transform([element | rest], fun, acc) do - new_transform(rest, fun, [fun.(element) | acc]) - end - @doc """ Returns whether the given `key` exists in the given `map`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/src/elixir_dispatch.erl new/elixir-1.12.2/lib/elixir/src/elixir_dispatch.erl --- old/elixir-1.12.1/lib/elixir/src/elixir_dispatch.erl 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/src/elixir_dispatch.erl 2021-07-01 18:15:34.000000000 +0200 @@ -77,7 +77,7 @@ end. remote_function(Meta, Receiver, Name, Arity, E) -> - check_deprecated(Meta, Receiver, Name, Arity, E), + check_deprecated(Meta, function, Receiver, Name, Arity, E), case elixir_rewrite:inline(Receiver, Name, Arity) of {AR, AN} -> {remote, AR, AN, Arity}; @@ -161,7 +161,7 @@ elixir_locals:record_import(Tuple, Receiver, Module, ?key(E, function)), {ok, Receiver, Name, Args}; {macro, Receiver} -> - check_deprecated(Meta, Receiver, Name, Arity, E), + check_deprecated(Meta, macro, Receiver, Name, Arity, E), elixir_env:trace({imported_macro, Meta, Receiver, Name, Arity}, E), elixir_locals:record_import(Tuple, Receiver, Module, ?key(E, function)), {ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)}; @@ -180,17 +180,18 @@ end. expand_require(Meta, Receiver, {Name, Arity} = Tuple, Args, E) -> - check_deprecated(Meta, Receiver, Name, Arity, E), Required = (Receiver == ?key(E, module)) orelse required(Meta) orelse is_element(Receiver, ?key(E, requires)), case is_element(Tuple, get_macros(Receiver, Required)) of true when Required -> + check_deprecated(Meta, macro, Receiver, Name, Arity, E), elixir_env:trace({remote_macro, Meta, Receiver, Name, Arity}, E), {ok, Receiver, expand_macro_named(Meta, Receiver, Name, Arity, Args, E)}; true -> Info = {unrequired_module, {Receiver, Name, length(Args)}}, elixir_errors:form_error(Meta, E, ?MODULE, Info); false -> + check_deprecated(Meta, function, Receiver, Name, Arity, E), error end. @@ -361,12 +362,13 @@ error:undef -> [] end. -check_deprecated(_, erlang, _, _, _) -> - ok; -check_deprecated(_, ?kernel, _, _, _) -> - ok; -check_deprecated(Meta, Receiver, Name, Arity, E) -> - case (?key(E, function) == nil) andalso get_deprecations(Receiver) of +check_deprecated(_, _, erlang, _, _, _) -> ok; +check_deprecated(_, _, elixir_def, _, _, _) -> ok; +check_deprecated(_, _, elixir_module, _, _, _) -> ok; +check_deprecated(_, _, ?kernel, _, _, _) -> ok; +check_deprecated(Meta, Kind, Receiver, Name, Arity, E) -> + %% Any compile time behaviour cannot be verified by the runtime group pass. + case ((?key(E, function) == nil) or (Kind == macro)) andalso get_deprecations(Receiver) of [_ | _] = Deprecations -> case lists:keyfind({Name, Arity}, 1, Deprecations) of {_, Message} -> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/src/elixir_erl_pass.erl new/elixir-1.12.2/lib/elixir/src/elixir_erl_pass.erl --- old/elixir-1.12.1/lib/elixir/src/elixir_erl_pass.erl 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/src/elixir_erl_pass.erl 2021-07-01 18:15:34.000000000 +0200 @@ -223,9 +223,9 @@ Ann = ?ann(Meta), TRight = {atom, Ann, Right}, - {Var, SV} = elixir_erl_var:build('_', SL), - TVar = {var, Ann, Var}, Generated = erl_anno:set_generated(true, Ann), + {Var, SV} = elixir_erl_var:build('_', SL), + TVar = {var, Generated, Var}, TError = {tuple, Ann, [{atom, Ann, badkey}, TRight, TVar]}, {{'case', Generated, TLeft, [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/test/elixir/enum_test.exs new/elixir-1.12.2/lib/elixir/test/elixir/enum_test.exs --- old/elixir-1.12.1/lib/elixir/test/elixir/enum_test.exs 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/test/elixir/enum_test.exs 2021-07-01 18:15:34.000000000 +0200 @@ -396,6 +396,8 @@ test "into/2" do assert Enum.into([a: 1, b: 2], %{}) == %{a: 1, b: 2} assert Enum.into([a: 1, b: 2], %{c: 3}) == %{a: 1, b: 2, c: 3} + assert Enum.into(MapSet.new(a: 1, b: 2), %{}) == %{a: 1, b: 2} + assert Enum.into(MapSet.new(a: 1, b: 2), %{c: 3}) == %{a: 1, b: 2, c: 3} assert Enum.into(%{a: 1, b: 2}, []) == [a: 1, b: 2] assert Enum.into(1..3, []) == [1, 2, 3] assert Enum.into(["H", "i"], "") == "Hi" @@ -405,7 +407,7 @@ assert Enum.into([1, 2, 3], [], fn x -> x * 2 end) == [2, 4, 6] assert Enum.into([1, 2, 3], "numbers: ", &to_string/1) == "numbers: 123" - assert_raise FunctionClauseError, fn -> + assert_raise MatchError, fn -> Enum.into([2, 3], %{a: 1}, & &1) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs new/elixir-1.12.2/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs --- old/elixir-1.12.1/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs 2021-07-01 18:15:34.000000000 +0200 @@ -202,5 +202,20 @@ assert URI in exports refute URI in runtime end + + test "compile_env! does not add a compile dependency" do + {{compile, exports, runtime, _}, _binding} = + Code.eval_string(""" + defmodule Kernel.LexicalTrackerTest.CompileEnvStruct do + Application.compile_env(:elixir, URI) + Application.compile_env(:elixir, [:foo, URI, :bar]) + Kernel.LexicalTracker.references(__ENV__.lexical_tracker) + end |> elem(3) + """) + + refute URI in compile + refute URI in exports + assert URI in runtime + end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/test/elixir/kernel/parallel_compiler_test.exs new/elixir-1.12.2/lib/elixir/test/elixir/kernel/parallel_compiler_test.exs --- old/elixir-1.12.1/lib/elixir/test/elixir/kernel/parallel_compiler_test.exs 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/test/elixir/kernel/parallel_compiler_test.exs 2021-07-01 18:15:34.000000000 +0200 @@ -43,7 +43,9 @@ assert HelloWorld in modules end) - assert profile =~ ~r"\[profile\] .*tmp/profile_time/bar.ex compiled in \d+ms" + assert profile =~ + ~r"\[profile\] [\s\d]{6}ms compiling \+ 0ms waiting for .*tmp/profile_time/bar.ex" + assert profile =~ ~r"\[profile\] Finished compilation cycle of 1 modules in \d+ms" assert profile =~ ~r"\[profile\] Finished group pass check of 1 modules in \d+ms" after diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/elixir/test/elixir/module/types/integration_test.exs new/elixir-1.12.2/lib/elixir/test/elixir/module/types/integration_test.exs --- old/elixir-1.12.1/lib/elixir/test/elixir/module/types/integration_test.exs 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/elixir/test/elixir/module/types/integration_test.exs 2021-07-01 18:15:34.000000000 +0200 @@ -663,6 +663,31 @@ assert_warnings(files, warning) end + + test "reports macro" do + files = %{ + "a.ex" => """ + defmodule A do + @deprecated "oops" + defmacro a, do: :ok + end + """, + "b.ex" => """ + defmodule B do + require A + def b, do: A.a() + end + """ + } + + warning = """ + warning: A.a/0 is deprecated. oops + b.ex:3: B.b/0 + + """ + + assert_warnings(files, warning) + end end defp assert_warnings(files, expected) when is_binary(expected) do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/mix/lib/mix/compilers/elixir.ex new/elixir-1.12.2/lib/mix/lib/mix/compilers/elixir.ex --- old/elixir-1.12.1/lib/mix/lib/mix/compilers/elixir.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/mix/lib/mix/compilers/elixir.ex 2021-07-01 18:15:34.000000000 +0200 @@ -226,6 +226,15 @@ dest ) + # Now sort the files so the ones changed more recently come first. + # We do an optimized version of sort_by since we don't care about + # stable sorting. + changed = + changed + |> Enum.map(&{-elem(Map.fetch!(sources_stats, &1), 0), &1}) + |> Enum.sort() + |> Enum.map(&elem(&1, 1)) + {modules, exports, changed, sources_stats} end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/mix/lib/mix/rebar.ex new/elixir-1.12.2/lib/mix/lib/mix/rebar.ex --- old/elixir-1.12.1/lib/mix/lib/mix/rebar.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/mix/lib/mix/rebar.ex 2021-07-01 18:15:34.000000000 +0200 @@ -123,7 +123,7 @@ # Translate a Rebar dependency declaration to a Mix declaration # From http://www.rebar3.org/docs/dependencies#section-declaring-dependencies defp parse_dep(app) when is_atom(app) do - {app, nil, override: true} + {app, override: true} end defp parse_dep({app, req}) when is_list(req) do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/mix/lib/mix/tasks/compile.all.ex new/elixir-1.12.2/lib/mix/lib/mix/tasks/compile.all.ex --- old/elixir-1.12.1/lib/mix/lib/mix/tasks/compile.all.ex 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/mix/lib/mix/tasks/compile.all.ex 2021-07-01 18:15:34.000000000 +0200 @@ -14,6 +14,7 @@ Mix.Project.get!() config = Mix.Project.config() validate_compile_env? = "--no-validate-compile-env" not in args + lib_path = Path.join(Mix.Project.build_path(config), "lib") # Make sure Mix.Dep is cached to avoid loading dependencies # during compilation. It is likely this will be invoked anyway, @@ -21,7 +22,7 @@ Mix.Dep.cached() unless "--no-app-loading" in args do - load_apps(config, validate_compile_env?) + load_apps(config, lib_path, validate_compile_env?) end result = @@ -39,8 +40,9 @@ end) end + app = config[:app] _ = Code.prepend_path(Mix.Project.compile_path()) - load_app(config[:app], validate_compile_env?) + load_app(app, lib_path, validate_compile_env?) result end @@ -93,44 +95,63 @@ ## App loading helpers - defp load_apps(config, validate_compile_env?) do + defp load_apps(config, lib_path, validate_compile_env?) do {runtime, optional} = Mix.Tasks.Compile.App.project_apps(config) + parent = self() + opts = [ordered: false, timeout: :infinity] + deps = for dep <- Mix.Dep.cached(), into: %{}, do: {dep.app, lib_path} + + stream_apps(runtime ++ optional, deps) + |> Task.async_stream(&load_stream_app(&1, parent, validate_compile_env?), opts) + |> Stream.run() + end + + defp load_stream_app({app, lib_path}, parent, validate_compile_env?) do + children = + case load_app(app, lib_path, validate_compile_env?) do + :ok -> + Application.spec(app, :applications) ++ Application.spec(app, :included_applications) - %{} - |> load_apps(runtime, validate_compile_env?) - |> load_apps(optional, validate_compile_env?) + :error -> + [] + end + send(parent, {:done, app, children}) :ok end - defp load_apps(seen, apps, validate_compile_env?) do - Enum.reduce(apps, seen, fn app, seen -> - if Map.has_key?(seen, app) do - seen - else - seen = Map.put(seen, app, true) + defp stream_apps(initial, deps) do + Stream.unfold({initial, %{}, %{}, deps}, &stream_app/1) + end - case load_app(app, validate_compile_env?) do - :ok -> - seen - |> load_apps(Application.spec(app, :applications), validate_compile_env?) - |> load_apps(Application.spec(app, :included_applications), validate_compile_env?) + # We already processed this app, skip it. + defp stream_app({[app | apps], seen, done, deps}) when is_map_key(seen, app) do + stream_app({apps, seen, done, deps}) + end - :error -> - seen - end - end - end) + # We haven't processed this app, emit it. + defp stream_app({[app | apps], seen, done, deps}) do + {{app, deps[app]}, {apps, Map.put(seen, app, true), done, deps}} + end + + # We have processed all apps and all seen have been done. + defp stream_app({[], seen, done, _deps}) when map_size(seen) == map_size(done) do + nil end - defp load_app(app, validate_compile_env?) do + # We have processed all apps but there is work being done. + defp stream_app({[], seen, done, deps}) do + receive do + {:done, app, children} -> stream_app({children, seen, Map.put(done, app, true), deps}) + end + end + + defp load_app(app, lib_path, validate_compile_env?) do if Application.spec(app, :vsn) do :ok else - name = Atom.to_charlist(app) ++ '.app' - - with [_ | _] = path <- :code.where_is_file(name), - {:ok, {:application, _, properties} = application_data} <- consult_app_file(path), + with {:ok, bin} <- read_app(app, lib_path), + {:ok, {:application, _, properties} = application_data} <- consult_app_file(bin), :ok <- :application.load(application_data) do if compile_env = validate_compile_env? && properties[:compile_env] do Config.Provider.validate_compile_env(compile_env, false) @@ -143,10 +164,22 @@ end end - defp consult_app_file(path) do + # The app didn't come from a dep, go through the slow path (code/erl_prim_loader) + defp read_app(app, nil) do + name = Atom.to_charlist(app) ++ '.app' + + with [_ | _] = path <- :code.where_is_file(name), + {:ok, bin, _full_name} <- :erl_prim_loader.get_file(path), + do: {:ok, bin} + end + + defp read_app(app, lib_path) do + File.read("#{lib_path}/#{app}/ebin/#{app}.app") + end + + defp consult_app_file(bin) do # The path could be located in an .ez archive, so we use the prim loader. - with {:ok, bin, _full_name} <- :erl_prim_loader.get_file(path), - {:ok, tokens, _} <- :erl_scan.string(String.to_charlist(bin)) do + with {:ok, tokens, _} <- :erl_scan.string(String.to_charlist(bin)) do :erl_parse.parse_term(tokens) end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elixir-1.12.1/lib/mix/test/mix/rebar_test.exs new/elixir-1.12.2/lib/mix/test/mix/rebar_test.exs --- old/elixir-1.12.1/lib/mix/test/mix/rebar_test.exs 2021-05-28 17:34:14.000000000 +0200 +++ new/elixir-1.12.2/lib/mix/test/mix/rebar_test.exs 2021-07-01 18:15:34.000000000 +0200 @@ -112,6 +112,8 @@ assert parse_dep({:git_rebar, '', {:git, @git_rebar_charlist, {:ref, '64691eb'}}}) == {:git_rebar, ~r"", override: true, git: @git_rebar_string, ref: "64691eb"} + + assert parse_dep(:git_rebar) == {:git_rebar, override: true} end end