Hello community,

here is the log from the commit of package elixir for openSUSE:Factory checked 
in at 2020-07-24 09:57:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/elixir (Old)
 and      /work/SRC/openSUSE:Factory/.elixir.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "elixir"

Fri Jul 24 09:57:15 2020 rev:11 rq:822142 version:1.10.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/elixir/elixir.changes    2020-04-27 
23:36:48.243338891 +0200
+++ /work/SRC/openSUSE:Factory/.elixir.new.3592/elixir.changes  2020-07-24 
09:59:09.669598618 +0200
@@ -1,0 +2,22 @@
+Wed Jul 8 08:09:49 UTC 2020 - Gabriele Santomaggio <[email protected]>
+
+- Elixir 1.10.4
+ * Bug fixes
+   Elixir
+   [Kernel] Fix a bug where custom types were printed as built-in types
+   [Kernel] Don't add compile-time dependency on defdelegate
+   [Kernel] Add line numbers to warnings on deprecated imports
+   [Kernel] Report the correct line number when raising inside a macro
+   [Task] Include callers in translated Logger metadata for Task
+   [Task] Fix Task PID and caller in Task Supervisor reports
+   ExUnit
+   [ExUnit.Formatter] Avoid crashes when diffing guards when the pattern does 
not match
+   [ExUnit.Formatter] Also blame exceptions that come from linked and trapped 
exits
+   IEx
+   [IEx.Helpers] Do not crash when printing a type that cannot be code 
formatted
+   Mix
+   [mix app.start] Fix reading .app file located in archives (.ez files)
+   [mix local.hex] Provide more guidance when Hex can't be installed
+   [mix release] Properly encode config in releases
+
+-------------------------------------------------------------------

Old:
----
  elixir-1.10.3.tar.gz

New:
----
  elixir-1.10.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ elixir-doc.spec ++++++
--- /var/tmp/diff_new_pack.FadwED/_old  2020-07-24 09:59:12.177600954 +0200
+++ /var/tmp/diff_new_pack.FadwED/_new  2020-07-24 09:59:12.181600957 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           elixir-doc
-Version:        1.10.3
+Version:        1.10.4
 Release:        0
 Summary:        Documentation for elixir
 License:        Apache-2.0
@@ -26,6 +26,7 @@
 Source0:        
https://github.com/elixir-lang/elixir/archive/v%{version}.tar.gz#/elixir-%{version}.tar.gz
 BuildRequires:  elixir
 BuildRequires:  elixir-ex_doc
+BuildRequires:  unzip
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildArch:      noarch
 Requires:       elixir = %{version}

++++++ elixir.spec ++++++
--- /var/tmp/diff_new_pack.FadwED/_old  2020-07-24 09:59:12.201600976 +0200
+++ /var/tmp/diff_new_pack.FadwED/_new  2020-07-24 09:59:12.205600980 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           elixir
-Version:        1.10.3
+Version:        1.10.4
 Release:        0
 Summary:        Functional meta-programming aware language built atop Erlang
 License:        Apache-2.0

++++++ elixir-1.10.3.tar.gz -> elixir-1.10.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/.cirrus.yml 
new/elixir-1.10.4/.cirrus.yml
--- old/elixir-1.10.3/.cirrus.yml       2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/.cirrus.yml       2020-07-04 13:10:47.000000000 +0200
@@ -27,16 +27,14 @@
         - env:
             CHECK_POSIX_COMPLIANT: true
             CHECK_REPRODUCIBLE: true
-            OTP_RELEASE: OTP-22.1
+            OTP_RELEASE: OTP-23.0
+        - env:
+            OTP_RELEASE: OTP-22.3
         - env:
             OTP_RELEASE: OTP-22.0
         - env:
             OTP_RELEASE: OTP-21.3.8
         - env:
-            OTP_RELEASE: OTP-21.2
-        - env:
-            OTP_RELEASE: OTP-21.1
-        - env:
             OTP_RELEASE: OTP-21.0
 
     - name: Linux, OTP-${OTP_RELEASE}, development, Ubuntu 14.04
@@ -110,7 +108,7 @@
     image: fertapric/elixir-ci:otp-win64-${OTP_RELEASE}
     os_version: ${OS_VERSION}
     cpu: 4
-    memory: 3840Mi
+    memory: 6GB
 
   install_script:
     - rmdir /s /q .git
@@ -143,7 +141,6 @@
     LC_ALL: en_US.UTF-8
 
   install_script:
-    - sudo pkg update
     - pkg install -y erlang git gmake
     - rm -rf .git
     - gmake compile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/CHANGELOG.md 
new/elixir-1.10.4/CHANGELOG.md
--- old/elixir-1.10.3/CHANGELOG.md      2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/CHANGELOG.md      2020-07-04 13:10:47.000000000 +0200
@@ -155,6 +155,34 @@
 
 Now imagine that `json_payload` is a large JSON blob and the `"key"` inside 
the `"body"` did not have value of `"foo"`. In previous Elixir versions, if the 
assertion failed, Elixir would print the right side and let you up to your own 
devices to figure out what went wrong. In Elixir v1.10, we diff the data 
structure against the pattern so you can see exactly which parts of the data 
matched the pattern and which ones did not. Note ExUnit already performed 
diffing when comparing data types, this new version adds diffing when matching 
data against a pattern.
 
+## v1.10.4 (2020-07-04)
+
+### 1. Bug fixes
+
+#### Elixir
+
+  * [Kernel] Fix a bug where custom types were printed as built-in types
+  * [Kernel] Don't add compile-time dependency on `defdelegate`
+  * [Kernel] Add line numbers to warnings on deprecated imports
+  * [Kernel] Report the correct line number when raising inside a macro
+  * [Task] Include callers in translated Logger metadata for Task
+  * [Task] Fix Task PID and caller in Task Supervisor reports
+
+#### ExUnit
+
+  * [ExUnit.Formatter] Avoid crashes when diffing guards when the pattern does 
not match
+  * [ExUnit.Formatter] Also blame exceptions that come from linked and trapped 
exits
+
+#### IEx
+
+  * [IEx.Helpers] Do not crash when printing a type that cannot be code 
formatted
+
+####  Mix
+
+  * [mix app.start] Fix reading `.app` file located in archives (`.ez` files)
+  * [mix local.hex] Provide more guidance when Hex can't be installed
+  * [mix release] Properly encode config in releases
+
 ## v1.10.3 (2020-04-25)
 
 ### 1. Bug fixes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/VERSION new/elixir-1.10.4/VERSION
--- old/elixir-1.10.3/VERSION   2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/VERSION   2020-07-04 13:10:47.000000000 +0200
@@ -1 +1 @@
-1.10.3
\ No newline at end of file
+1.10.4
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/code/typespec.ex 
new/elixir-1.10.4/lib/elixir/lib/code/typespec.ex
--- old/elixir-1.10.3/lib/elixir/lib/code/typespec.ex   2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/lib/code/typespec.ex   2020-07-04 
13:10:47.000000000 +0200
@@ -217,7 +217,8 @@
   end
 
   defp typespec_to_quoted({:user_type, line, name, args}) do
-    typespec_to_quoted({:type, line, name, args})
+    args = for arg <- args, do: typespec_to_quoted(arg)
+    {name, [line: line], args}
   end
 
   defp typespec_to_quoted({:type, line, :tuple, :any}) do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/config/provider.ex 
new/elixir-1.10.4/lib/elixir/lib/config/provider.ex
--- old/elixir-1.10.3/lib/elixir/lib/config/provider.ex 2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/lib/config/provider.ex 2020-07-04 
13:10:47.000000000 +0200
@@ -350,7 +350,7 @@
   defp write_config!(config, path) do
     contents = :io_lib.format("%% coding: utf-8~n~tw.~n", [config])
 
-    case File.write(path, contents, [:utf8]) do
+    case File.write(path, IO.chardata_to_string(contents)) do
       :ok ->
         :ok
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/io.ex 
new/elixir-1.10.4/lib/elixir/lib/io.ex
--- old/elixir-1.10.3/lib/elixir/lib/io.ex      2020-04-25 10:30:20.000000000 
+0200
+++ new/elixir-1.10.4/lib/elixir/lib/io.ex      2020-07-04 13:10:47.000000000 
+0200
@@ -317,7 +317,7 @@
   @spec warn(chardata | String.Chars.t(), Exception.stacktrace()) :: :ok
   def warn(message, []) do
     message = [to_chardata(message), ?\n]
-    :elixir_errors.io_warn(nil, nil, message, message)
+    :elixir_errors.io_warn(0, nil, message, message)
   end
 
   def warn(message, [{_, _, _, opts} | _] = stacktrace) do
@@ -327,7 +327,7 @@
     file = opts[:file]
 
     :elixir_errors.io_warn(
-      line,
+      line || 0,
       file && List.to_string(file),
       message,
       [message, ?\n, "  ", formatted_trace, ?\n]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/lib/kernel/parallel_compiler.ex 
new/elixir-1.10.4/lib/elixir/lib/kernel/parallel_compiler.ex
--- old/elixir-1.10.3/lib/elixir/lib/kernel/parallel_compiler.ex        
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/lib/kernel/parallel_compiler.ex        
2020-07-04 13:10:47.000000000 +0200
@@ -652,6 +652,12 @@
     end
   end
 
+  defp get_line(file, _reason, [{_, _, _, [file: 'expanding macro']}, {_, _, 
_, info} | _]) do
+    if Keyword.get(info, :file) == to_charlist(Path.relative_to_cwd(file)) do
+      Keyword.get(info, :line)
+    end
+  end
+
   defp get_line(file, _reason, [{_, _, _, info} | _]) do
     if Keyword.get(info, :file) == to_charlist(Path.relative_to_cwd(file)) do
       Keyword.get(info, :line)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/kernel.ex 
new/elixir-1.10.4/lib/elixir/lib/kernel.ex
--- old/elixir-1.10.3/lib/elixir/lib/kernel.ex  2020-04-25 10:30:20.000000000 
+0200
+++ new/elixir-1.10.4/lib/elixir/lib/kernel.ex  2020-07-04 13:10:47.000000000 
+0200
@@ -4881,6 +4881,18 @@
   defmacro defdelegate(funs, opts) do
     funs = Macro.escape(funs, unquote: true)
 
+    # don't add compile-time dependency on :to
+    opts =
+      with true <- is_list(opts),
+           {:ok, target} <- Keyword.fetch(opts, :to),
+           {:__aliases__, _, _} <- target do
+        target = Macro.expand(target, %{__CALLER__ | function: {:__info__, 1}})
+        Keyword.replace!(opts, :to, target)
+      else
+        _ ->
+          opts
+      end
+
     quote bind_quoted: [funs: funs, opts: opts] do
       target =
         Keyword.get(opts, :to) || raise ArgumentError, "expected to: to be 
given as argument"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/module/checker.ex 
new/elixir-1.10.4/lib/elixir/lib/module/checker.ex
--- old/elixir-1.10.3/lib/elixir/lib/module/checker.ex  2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/lib/module/checker.ex  2020-07-04 
13:10:47.000000000 +0200
@@ -231,7 +231,7 @@
 
   defp warn(meta, state, warning) do
     {fun, arity} = state.function
-    location = {state.file, meta[:line], {state.module, fun, arity}}
+    location = {state.file, meta[:line] || 0, {state.module, fun, arity}}
     %{state | warnings: [{__MODULE__, warning, location} | state.warnings]}
   end
 
@@ -306,7 +306,7 @@
 
   defp format_location({file, line, {module, fun, arity}}) do
     file = Path.relative_to_cwd(file)
-    line = if line, do: [Integer.to_string(line), ": "], else: []
+    line = if line > 0, do: [Integer.to_string(line), ": "], else: []
     mfa = Exception.format_mfa(module, fun, arity)
     ["  ", file, ?:, line, mfa, ?\n]
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/lib/task/supervised.ex 
new/elixir-1.10.4/lib/elixir/lib/task/supervised.ex
--- old/elixir-1.10.3/lib/elixir/lib/task/supervised.ex 2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/lib/task/supervised.ex 2020-07-04 
13:10:47.000000000 +0200
@@ -102,8 +102,8 @@
           %{
             label: {Task.Supervisor, :terminating},
             report: %{
-              name: get_from(owner),
-              starter: self(),
+              name: self(),
+              starter: get_from(owner),
               function: fun,
               args: args,
               reason: {log_value(kind, value), __STACKTRACE__}
@@ -112,7 +112,8 @@
           %{
             domain: [:otp, :elixir],
             error_logger: %{tag: :error_msg},
-            report_cb: &__MODULE__.format_report/1
+            report_cb: &__MODULE__.format_report/1,
+            callers: Process.get(:"$callers")
           }
         )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' "old/elixir-1.10.3/lib/elixir/pages/Compatibility and 
Deprecations.md" "new/elixir-1.10.4/lib/elixir/pages/Compatibility and 
Deprecations.md"
--- "old/elixir-1.10.3/lib/elixir/pages/Compatibility and Deprecations.md"      
2020-04-25 10:30:20.000000000 +0200
+++ "new/elixir-1.10.4/lib/elixir/pages/Compatibility and Deprecations.md"      
2020-07-04 13:10:47.000000000 +0200
@@ -52,7 +52,7 @@
 1.7            | 19 - 22
 1.8            | 20 - 22
 1.9            | 20 - 22
-1.10           | 21 - 22
+1.10           | 21 - 22 (and Erlang/OTP 23 from v1.10.3)
 
 While Elixir often adds compatibility to new Erlang/OTP versions on released 
branches, such as support for Erlang/OTP 20 in v1.4.5, those releases usually 
contain the minimum changes for Elixir to run without errors. Only the next 
minor release, in this case v1.5.0, does effectively leverage the new features 
provided by the latest Erlang/OTP release.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/elixir/src/elixir_dispatch.erl 
new/elixir-1.10.4/lib/elixir/src/elixir_dispatch.erl
--- old/elixir-1.10.3/lib/elixir/src/elixir_dispatch.erl        2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/src/elixir_dispatch.erl        2020-07-04 
13:10:47.000000000 +0200
@@ -92,7 +92,7 @@
     {ok, Receiver, Quoted} ->
       expand_quoted(Meta, Receiver, Name, Arity, Quoted, E);
     {ok, Receiver, NewName, NewArgs} ->
-      elixir_expand:expand({{'.', [], [Receiver, NewName]}, Meta, NewArgs}, E);
+      elixir_expand:expand({{'.', Meta, [Receiver, NewName]}, Meta, NewArgs}, 
E);
     error ->
       Callback()
   end.
@@ -328,9 +328,10 @@
   end;
 
 get_macros(Receiver, true) ->
-  case is_ensure_loaded(Receiver) of
-    true -> get_info(Receiver, macros);
-    false -> []
+  try
+    Receiver:'__info__'(macros)
+  catch
+    error:_ -> []
   end.
 
 %% Kernel deprecations are inlined.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/test/elixir/config/provider_test.exs 
new/elixir-1.10.4/lib/elixir/test/elixir/config/provider_test.exs
--- old/elixir-1.10.3/lib/elixir/test/elixir/config/provider_test.exs   
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/test/elixir/config/provider_test.exs   
2020-07-04 13:10:47.000000000 +0200
@@ -83,11 +83,11 @@
       assert config[@config_app] == [config_providers_booted: {:booted, nil}]
     end
 
-    @tag sys_config: [my_app: [encoding: {:"£", "£", '£'}]]
+    @tag sys_config: [my_app: [encoding: {:time_μs, :"£", "£", '£'}]]
     test "writes sys_config with encoding" do
       init_and_assert_boot()
       config = consult(@sys_config)
-      assert config[:my_app][:encoding] == {:"£", "£", '£'}
+      assert config[:my_app][:encoding] == {:time_μs, :"£", "£", '£'}
     end
 
     @tag sys_config: [my_app: [key: :old_value, sys_key: :sys_value, 
extra_config: :old_value]]
@@ -185,6 +185,6 @@
   end
 
   defp write_sys_config!(data) do
-    File.write!(@sys_config, :io_lib.format("~tw.~n", [data]), [:utf8])
+    File.write!(@sys_config, IO.chardata_to_string(:io_lib.format("~tw.~n", 
[data])))
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/test/elixir/kernel/expansion_test.exs 
new/elixir-1.10.4/lib/elixir/test/elixir/kernel/expansion_test.exs
--- old/elixir-1.10.3/lib/elixir/test/elixir/kernel/expansion_test.exs  
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/test/elixir/kernel/expansion_test.exs  
2020-07-04 13:10:47.000000000 +0200
@@ -654,8 +654,8 @@
         expand(quote(do: [1] ++ 2 ++ [3] = [1, 2, 3]))
       end
 
-      assert {:=, _, [-1, {{:., [], [:erlang, :-]}, _, [1]}]} = 
expand(quote(do: -1 = -1))
-      assert {:=, _, [1, {{:., [], [:erlang, :+]}, _, [1]}]} = 
expand(quote(do: +1 = +1))
+      assert {:=, _, [-1, {{:., _, [:erlang, :-]}, _, [1]}]} = 
expand(quote(do: -1 = -1))
+      assert {:=, _, [1, {{:., _, [:erlang, :+]}, _, [1]}]} = expand(quote(do: 
+1 = +1))
 
       assert {:=, _, [[{:|, _, [1, [{:|, _, [2, 3]}]]}], [1, 2, 3]]} =
                expand(quote(do: [1] ++ [2] ++ 3 = [1, 2, 3]))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs 
new/elixir-1.10.4/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs
--- old/elixir-1.10.3/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs    
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/test/elixir/kernel/lexical_tracker_test.exs    
2020-07-04 13:10:47.000000000 +0200
@@ -126,4 +126,21 @@
     refute Foo.Bar in runtime
     refute Foo.Bar in compile
   end
+
+  test "defdelegate with literal does not add compile dependency" do
+    {{compile, _structs, _runtime, _}, _binding} =
+      Code.eval_string("""
+      defmodule Kernel.LexicalTrackerTest.Defdelegate do
+        defdelegate a, to: A
+
+        opts = [to: B]
+        defdelegate b, opts
+
+        Kernel.LexicalTracker.references(__ENV__.lexical_tracker)
+      end |> elem(3)
+      """)
+
+    refute A in compile
+    assert B in compile
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/test/elixir/module/checker_test.exs 
new/elixir-1.10.4/lib/elixir/test/elixir/module/checker_test.exs
--- old/elixir-1.10.3/lib/elixir/test/elixir/module/checker_test.exs    
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/test/elixir/module/checker_test.exs    
2020-07-04 13:10:47.000000000 +0200
@@ -639,6 +639,31 @@
       assert_warnings(files, warning)
     end
 
+    test "reports imported functions" do
+      files = %{
+        "a.ex" => """
+        defmodule A do
+          @deprecated "oops"
+          def a, do: :ok
+        end
+        """,
+        "b.ex" => """
+        defmodule B do
+          import A
+          def b, do: a()
+        end
+        """
+      }
+
+      warning = """
+      warning: A.a/0 is deprecated. oops
+        b.ex:3: B.b/0
+
+      """
+
+      assert_warnings(files, warning)
+    end
+
     test "reports structs" do
       files = %{
         "a.ex" => """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/elixir/test/elixir/typespec_test.exs 
new/elixir-1.10.4/lib/elixir/test/elixir/typespec_test.exs
--- old/elixir-1.10.3/lib/elixir/test/elixir/typespec_test.exs  2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/elixir/test/elixir/typespec_test.exs  2020-07-04 
13:10:47.000000000 +0200
@@ -1183,6 +1183,12 @@
       quoted =
         Enum.sort([
           quote(do: @spec(foo() :: integer())),
+          quote(do: @spec(foo() :: union())),
+          quote(do: @spec(foo() :: union(integer()))),
+          quote(do: @spec(foo() :: truly_union())),
+          quote(do: @spec(foo(union()) :: union())),
+          quote(do: @spec(foo(union(integer())) :: union(integer()))),
+          quote(do: @spec(foo(truly_union()) :: truly_union())),
           quote(do: @spec(foo(atom()) :: integer() | [{}])),
           quote(do: @spec(foo(arg) :: integer() when [arg: integer()])),
           quote(do: @spec(foo(arg) :: arg when [arg: var])),
@@ -1191,6 +1197,10 @@
 
       bytecode =
         test_module do
+          @type union :: any()
+          @type union(t) :: t
+          @type truly_union :: list | map | union
+
           def foo(), do: 1
           def foo(arg), do: arg
           Module.eval_quoted(__MODULE__, quote(do: (unquote_splicing(quoted))))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/ex_unit/examples/one_of_each.exs 
new/elixir-1.10.4/lib/ex_unit/examples/one_of_each.exs
--- old/elixir-1.10.3/lib/ex_unit/examples/one_of_each.exs      2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/ex_unit/examples/one_of_each.exs      2020-07-04 
13:10:47.000000000 +0200
@@ -1,4 +1,4 @@
-ExUnit.start [seed: 0]
+ExUnit.start(seed: 0)
 
 defmodule TestOneOfEach do
   @moduledoc """
@@ -10,8 +10,8 @@
   @one 1
   @two 2
 
-  @long_data_1  [field1: "one", field2: {:two1, :two2}, field3: 'three', 
field4: [1, 2, 3, 4]]
-  @long_data_2  [field1: "one", field2: {:two1, :two3}, field3: 'three', 
field4: [1, 2, 3, 4]]
+  @long_data_1 [field1: "one", field2: {:two1, :two2}, field3: 'three', 
field4: [1, 2, 3, 4]]
+  @long_data_2 [field1: "one", field2: {:two1, :two3}, field3: 'three', 
field4: [1, 2, 3, 4]]
 
   setup do
     {:ok, user_id: 1, post_id: 2, many_ids: Enum.to_list(1..50)}
@@ -62,10 +62,10 @@
   end
 
   test "12. assert that a message is received within a timeout" do
-    send self(), {:ok, 1}
-    send self(), :message_in_my_inbox
-    send self(), {:ok, 2}
-    send self(), :another_message
+    send(self(), {:ok, 1})
+    send(self(), :message_in_my_inbox)
+    send(self(), {:ok, 2})
+    send(self(), :another_message)
     assert_receive :no_message_after_timeout
   end
 
@@ -75,14 +75,14 @@
 
   test "14. assert an exception with a given message is raised" do
     assert_raise(SomeException, "some message", fn ->
-                                                     raise "other exception"
-                                                end)
+      raise "other exception"
+    end)
   end
 
   test "15. assert an exception with a given message is raised, but the 
message is wrong" do
     assert_raise(RuntimeError, "some message", fn ->
-                                                    raise "other error"
-                                               end)
+      raise "other error"
+    end)
   end
 
   test "16. assert an exception is raised" do
@@ -90,7 +90,7 @@
   end
 
   test "17. assert two values are within some delta" do
-    assert_in_delta 3.1415926, 22.0/7, 0.001
+    assert_in_delta 3.1415926, 22.0 / 7, 0.001
   end
 
   test "18. refute a value with a message" do
@@ -98,12 +98,12 @@
   end
 
   test "19. refute a message is received within a timeout" do
-    send self(), {:hello, "Dave"}
+    send(self(), {:hello, "Dave"})
     refute_receive {:hello, _}, 1000
   end
 
   test "20. refute a message is ready to be received" do
-    send self(), :hello_again
+    send(self(), :hello_again)
     refute_received :hello_again
   end
 
@@ -116,7 +116,7 @@
   end
 
   test "23. flunk" do
-    flunk "we failed. totally"
+    flunk("we failed. totally")
   end
 
   test "24. exception raised while running test" do
@@ -124,7 +124,8 @@
   end
 
   test "25. error due to exit" do
-    spawn_link fn -> raise "oops" end
+    spawn_link(fn -> raise "oops" end)
+
     receive do
     end
   end
@@ -133,15 +134,17 @@
     error1 =
       try do
         assert [@one] = [@two]
-      rescue e in ExUnit.AssertionError ->
-        {:error, e, System.stacktrace}
+      rescue
+        e in ExUnit.AssertionError ->
+          {:error, e, __STACKTRACE__}
       end
 
     error2 =
       try do
         assert @one * 4 > @two * 3
-      rescue e in ExUnit.AssertionError ->
-        {:error, e, System.stacktrace}
+      rescue
+        e in ExUnit.AssertionError ->
+          {:error, e, __STACKTRACE__}
       end
 
     raise ExUnit.MultiError, errors: [error1, error2]
@@ -150,8 +153,8 @@
   @tag capture_log: true
   test "27. log capturing" do
     require Logger
-    Logger.debug "this will be logged"
-    flunk "oops"
+    Logger.debug("this will be logged")
+    flunk("oops")
   end
 
   test "28. function clause error" do
@@ -162,6 +165,28 @@
     assert some_vars(1 + 2, 3 + 4)
   end
 
+  @tag :capture_log
+  test "30. linked assertion error" do
+    Task.async(fn -> assert 1 == 2 end) |> Task.await()
+  end
+
+  @tag :capture_log
+  test "31. linked function clause error" do
+    Task.async(fn -> Access.fetch(:foo, :bar) end) |> Task.await()
+  end
+
+  @tag :capture_log
+  test "32. trapped assertion error" do
+    Process.flag(:trap_exit, true)
+    Task.async(fn -> assert 1 == 2 end) |> Task.await()
+  end
+
+  @tag :capture_log
+  test "33. trapped function clause error" do
+    Process.flag(:trap_exit, true)
+    Task.async(fn -> Access.fetch(:foo, :bar) end) |> Task.await()
+  end
+
   defp some_vars(_a, _b) do
     false
   end
@@ -171,6 +196,6 @@
   end
 
   defp ignite(val) do
-    1/val
+    1 / val
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/ex_unit/lib/ex_unit/diff.ex 
new/elixir-1.10.4/lib/ex_unit/lib/ex_unit/diff.ex
--- old/elixir-1.10.3/lib/ex_unit/lib/ex_unit/diff.ex   2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/ex_unit/lib/ex_unit/diff.ex   2020-07-04 
13:10:47.000000000 +0200
@@ -180,13 +180,18 @@
   defp diff_guard({:when, _, [expression, clause]}, right, env) do
     {diff_expression, post_env} = diff_quoted(expression, right, env)
 
-    bindings = Map.merge(post_env.pins, post_env.current_vars)
-    {diff_clause, clause_equivalent?} = diff_guard_clause(clause, 
Map.to_list(bindings))
+    {guard_clause, guard_equivalent?} =
+      if diff_expression.equivalent? do
+        bindings = Map.merge(post_env.pins, post_env.current_vars)
+        diff_guard_clause(clause, Map.to_list(bindings))
+      else
+        {clause, false}
+      end
 
     diff = %__MODULE__{
       diff_expression
-      | left: {:when, [], [diff_expression.left, diff_clause]},
-        equivalent?: diff_expression.equivalent? and clause_equivalent?
+      | left: {:when, [], [diff_expression.left, guard_clause]},
+        equivalent?: guard_equivalent?
     }
 
     {diff, post_env}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/ex_unit/lib/ex_unit/formatter.ex 
new/elixir-1.10.4/lib/ex_unit/lib/ex_unit/formatter.ex
--- old/elixir-1.10.3/lib/ex_unit/lib/ex_unit/formatter.ex      2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/ex_unit/lib/ex_unit/formatter.ex      2020-07-04 
13:10:47.000000000 +0200
@@ -54,6 +54,7 @@
 
   @counter_padding "     "
   @mailbox_label_padding @counter_padding <> "  "
+  @formatter_exceptions [ExUnit.AssertionError, FunctionClauseError]
   @no_value ExUnit.AssertionError.no_value()
 
   @doc """
@@ -136,10 +137,10 @@
 
   @doc false
   def format_assertion_error(%ExUnit.AssertionError{} = struct) do
-    format_assertion_error(%{}, struct, [], :infinity, fn _, msg -> msg end, 
"")
+    format_exception(%{}, struct, [], :infinity, fn _, msg -> msg end, "") |> 
elem(0)
   end
 
-  defp format_assertion_error(test, struct, stack, width, formatter, 
counter_padding) do
+  defp format_exception(test, %ExUnit.AssertionError{} = struct, stack, width, 
formatter, pad) do
     label_padding_size = if has_value?(struct.right), do: 7, else: 6
     padding_size = label_padding_size + byte_size(@counter_padding)
 
@@ -148,16 +149,27 @@
         do: &pad_multiline(&1, padding_size),
         else: &code_multiline(&1, padding_size)
 
-    [
-      note: if_value(struct.message, &format_message(&1, formatter)),
-      doctest: if_value(struct.doctest, &pad_multiline(&1, 2 + 
byte_size(@counter_padding))),
-      code: if_value(struct.expr, code_multiline),
-      code: unless_value(struct.expr, fn -> get_code(test, stack) || @no_value 
end),
-      arguments: if_value(struct.args, &format_args(&1, width))
-    ]
-    |> Kernel.++(format_context(struct, formatter, padding_size, width))
-    |> format_meta(formatter, counter_padding, label_padding_size)
-    |> IO.iodata_to_binary()
+    formatted =
+      [
+        note: if_value(struct.message, &format_message(&1, formatter)),
+        doctest: if_value(struct.doctest, &pad_multiline(&1, 2 + 
byte_size(@counter_padding))),
+        code: if_value(struct.expr, code_multiline),
+        code: unless_value(struct.expr, fn -> get_code(test, stack) || 
@no_value end),
+        arguments: if_value(struct.args, &format_args(&1, width))
+      ]
+      |> Kernel.++(format_context(struct, formatter, padding_size, width))
+      |> format_meta(formatter, pad, label_padding_size)
+      |> IO.iodata_to_binary()
+
+    {formatted, stack}
+  end
+
+  defp format_exception(test, %FunctionClauseError{} = struct, stack, _width, 
formatter, _pad) do
+    {blamed, stack} = Exception.blame(:error, struct, stack)
+    banner = Exception.format_banner(:error, struct)
+    blamed = FunctionClauseError.blame(blamed, &inspect/1, &blame_match(&1, 
&2, formatter))
+    message = error_info(banner, formatter) <> "\n" <> 
pad(String.trim_leading(blamed, "\n"))
+    {message <> format_code(test, stack, formatter), stack}
   end
 
   @doc false
@@ -179,29 +191,47 @@
       end)
   end
 
-  defp format_kind_reason(
-         test,
-         :error,
-         %ExUnit.AssertionError{} = struct,
-         stack,
-         width,
-         formatter
-       ) do
-    {format_assertion_error(test, struct, stack, width, formatter, 
@counter_padding), stack}
+  defp format_kind_reason(test, :error, %mod{} = struct, stack, width, 
formatter)
+       when mod in @formatter_exceptions do
+    format_exception(test, struct, stack, width, formatter, @counter_padding)
+  end
+
+  defp format_kind_reason(test, kind, reason, stack, width, formatter) do
+    case linked_or_trapped_exit(kind, reason) do
+      {header, wrapped_reason, wrapped_stack} ->
+        struct = Exception.normalize(:error, wrapped_reason, wrapped_stack)
+
+        {formatted_reason, _} =
+          format_exception(test, struct, wrapped_stack, width, formatter, 
@counter_padding)
+
+        formatted_stack = format_stacktrace(wrapped_stack, test.module, 
test.name, formatter)
+        {error_info(header, formatter) <> pad(formatted_reason <> 
formatted_stack), stack}
+
+      :error ->
+        {reason, stack} = Exception.blame(kind, reason, stack)
+        message = error_info(Exception.format_banner(kind, reason), formatter)
+        {message <> format_code(test, stack, formatter), stack}
+    end
   end
 
-  defp format_kind_reason(test, :error, %FunctionClauseError{} = struct, 
stack, _width, formatter) do
-    {blamed, stack} = Exception.blame(:error, struct, stack)
-    banner = Exception.format_banner(:error, struct)
-    blamed = FunctionClauseError.blame(blamed, &inspect/1, &blame_match(&1, 
&2, formatter))
-    message = error_info(banner, formatter) <> "\n" <> 
pad(String.trim_leading(blamed, "\n"))
-    {message <> format_code(test, stack, formatter), stack}
+  defp linked_or_trapped_exit({:EXIT, pid}, {reason, [_ | _] = stack})
+       when :erlang.map_get(:__struct__, reason) in @formatter_exceptions
+       when reason == :function_clause do
+    {"** (EXIT from #{inspect(pid)}) an exception was raised:\n", reason, 
stack}
+  end
+
+  defp linked_or_trapped_exit(:exit, {{reason, [_ | _] = stack}, {mod, fun, 
args}})
+       when is_atom(mod) and is_atom(fun) and is_list(args) and
+              :erlang.map_get(:__struct__, reason) in @formatter_exceptions
+       when is_atom(mod) and is_atom(fun) and is_list(args) and reason == 
:function_clause do
+    {
+      "** (exit) exited in: #{Exception.format_mfa(mod, fun, args)}\n   ** 
(EXIT) an exception was raised:",
+      reason,
+      stack
+    }
   end
 
-  defp format_kind_reason(test, kind, reason, stack, _width, formatter) do
-    message = error_info(Exception.format_banner(kind, reason), formatter)
-    {message <> format_code(test, stack, formatter), stack}
-  end
+  defp linked_or_trapped_exit(_kind, _reason), do: :error
 
   defp format_code(test, stack, formatter) do
     if snippet = get_code(test, stack) do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/ex_unit/test/ex_unit/diff_test.exs 
new/elixir-1.10.4/lib/ex_unit/test/ex_unit/diff_test.exs
--- old/elixir-1.10.3/lib/ex_unit/test/ex_unit/diff_test.exs    2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/ex_unit/test/ex_unit/diff_test.exs    2020-07-04 
13:10:47.000000000 +0200
@@ -914,6 +914,7 @@
     refute_diff((x when x == 1 or x == 2) = 0, "x when -x == 1- or -x == 2-", 
"0")
     refute_diff((x when x == 1 when x == 2) = 0, "x when -x == 1- when -x == 
2-", "0")
     refute_diff((x when x in [1, 2]) = 0, "x when -x in [1, 2]-", "0")
+    refute_diff(({:ok, x} when x == 1) = :error, "-{:ok, x}- when x == 1", 
"+:error+")
   end
 
   test "charlists" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/ex_unit/test/ex_unit/formatter_test.exs 
new/elixir-1.10.4/lib/ex_unit/test/ex_unit/formatter_test.exs
--- old/elixir-1.10.3/lib/ex_unit/test/ex_unit/formatter_test.exs       
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/ex_unit/test/ex_unit/formatter_test.exs       
2020-07-04 13:10:47.000000000 +0200
@@ -69,6 +69,61 @@
            """
   end
 
+  test "formats test exits with function clause mfa" do
+    {error, stack} =
+      try do
+        Access.fetch(:foo, :bar)
+      catch
+        :error, error -> {error, __STACKTRACE__}
+      end
+
+    failure = [{:exit, {{error, stack}, {:mod, :fun, []}}, []}]
+
+    assert trim_multiline_whitespace(format_test_failure(test(), failure, 1, 
80, &formatter/2)) =~
+             """
+               1) world (Hello)
+                  test/ex_unit/formatter_test.exs:1
+                  ** (exit) exited in: :mod.fun()
+                     ** (EXIT) an exception was raised:
+                       ** (FunctionClauseError) no function clause matching in 
Access.fetch/2
+
+                       The following arguments were given to Access.fetch/2:
+
+                           # 1
+                           :foo
+
+                           # 2
+                           :bar
+
+                       Attempted function clauses (showing 5 out of 5):
+
+                           def fetch(%module{} = container, key)
+             """
+  end
+
+  test "formats test exits with assertion mfa" do
+    {error, stack} =
+      try do
+        assert 1 == 2
+      rescue
+        error -> {error, __STACKTRACE__}
+      end
+
+    failure = [{:exit, {{error, stack}, {:mod, :fun, []}}, []}]
+
+    assert trim_multiline_whitespace(format_test_failure(test(), failure, 1, 
80, &formatter/2)) =~
+             """
+               1) world (Hello)
+                  test/ex_unit/formatter_test.exs:1
+                  ** (exit) exited in: :mod.fun()
+                     ** (EXIT) an exception was raised:
+                       Assertion with == failed
+                       code:  assert 1 == 2
+                       left:  1
+                       right: 2
+             """
+  end
+
   test "formats test throws" do
     failure = [{:throw, 1, []}]
 
@@ -89,6 +144,61 @@
            """
   end
 
+  test "formats test EXITs with function clause errors" do
+    {error, stack} =
+      try do
+        Access.fetch(:foo, :bar)
+      catch
+        :error, error -> {error, __STACKTRACE__}
+      end
+
+    failure = [{{:EXIT, self()}, {error, stack}, []}]
+
+    assert trim_multiline_whitespace(format_test_failure(test(), failure, 1, 
80, &formatter/2)) =~
+             """
+               1) world (Hello)
+                  test/ex_unit/formatter_test.exs:1
+                  ** (EXIT from #{inspect(self())}) an exception was raised:
+
+                       ** (FunctionClauseError) no function clause matching in 
Access.fetch/2
+
+                       The following arguments were given to Access.fetch/2:
+
+                           # 1
+                           :foo
+
+                           # 2
+                           :bar
+
+                       Attempted function clauses (showing 5 out of 5):
+
+                           def fetch(%module{} = container, key)
+             """
+  end
+
+  test "formats test EXITs with assertion errors" do
+    {error, stack} =
+      try do
+        assert 1 == 2
+      rescue
+        error -> {error, __STACKTRACE__}
+      end
+
+    failure = [{{:EXIT, self()}, {error, stack}, []}]
+
+    assert trim_multiline_whitespace(format_test_failure(test(), failure, 1, 
80, &formatter/2)) =~
+             """
+               1) world (Hello)
+                  test/ex_unit/formatter_test.exs:1
+                  ** (EXIT from #{inspect(self())}) an exception was raised:
+
+                       Assertion with == failed
+                       code:  assert 1 == 2
+                       left:  1
+                       right: 2
+             """
+  end
+
   test "formats test errors with test_location_relative_path" do
     Application.put_env(:ex_unit, :test_location_relative_path, "apps/sample")
     failure = [{:error, catch_error(raise "oops"), []}]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/iex/lib/iex/introspection.ex 
new/elixir-1.10.4/lib/iex/lib/iex/introspection.ex
--- old/elixir-1.10.3/lib/iex/lib/iex/introspection.ex  2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/iex/lib/iex/introspection.ex  2020-07-04 
13:10:47.000000000 +0200
@@ -735,9 +735,15 @@
   ## Helpers
 
   defp format_typespec(definition, kind, nesting) do
-    "@#{kind} #{Macro.to_string(definition)}"
-    |> Code.format_string!(line_length: IEx.width() - 2 * nesting)
-    |> IO.iodata_to_binary()
+    string = "@#{kind} #{Macro.to_string(definition)}"
+
+    try do
+      string
+      |> Code.format_string!(line_length: IEx.width() - 2 * nesting)
+      |> IO.iodata_to_binary()
+    rescue
+      _ -> string
+    end
     |> color_prefix_with_line()
     |> indent(nesting)
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/iex/test/iex/helpers_test.exs 
new/elixir-1.10.4/lib/iex/test/iex/helpers_test.exs
--- old/elixir-1.10.3/lib/iex/test/iex/helpers_test.exs 2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/iex/test/iex/helpers_test.exs 2020-07-04 
13:10:47.000000000 +0200
@@ -853,6 +853,7 @@
       defmodule TypeSample do
         @typedoc "An ID with description."
         @type id_with_desc :: {number, String.t}
+        @type unquote(:"?")() :: :question_mark
       end
       """
 
@@ -872,6 +873,11 @@
 
                An ID with description.
                """
+
+        assert capture_io(fn -> t(TypeSample."?"()) end) == """
+               @type ?() :: :question_mark
+
+               """
       end)
     after
       cleanup_modules([TypeSample])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/logger/test/logger/translator_test.exs 
new/elixir-1.10.4/lib/logger/test/logger/translator_test.exs
--- old/elixir-1.10.3/lib/logger/test/logger/translator_test.exs        
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/logger/test/logger/translator_test.exs        
2020-07-04 13:10:47.000000000 +0200
@@ -306,13 +306,14 @@
 
   test "translates Task crashes" do
     {:ok, pid} = Task.start_link(__MODULE__, :task, [self()])
+    parent = self()
 
     assert capture_log(fn ->
              ref = Process.monitor(pid)
              send(pid, :go)
              receive do: ({:DOWN, ^ref, _, _, _} -> :ok)
            end) =~ ~r"""
-           \[error\] Task #PID<\d+\.\d+\.\d+> started from #PID<\d+\.\d+\.\d+> 
terminating
+           \[error\] Task #{inspect(pid)} started from #{inspect(self())} 
terminating
            \*\* \(RuntimeError\) oops
            .*
            Function: &Logger.TranslatorTest.task\/1
@@ -324,6 +325,7 @@
 
     assert {%RuntimeError{message: "oops"}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%RuntimeError{message: "oops"}, [_ | _]} = 
process_metadata[:crash_reason]
+    assert [parent] == task_metadata[:callers]
 
     refute Keyword.has_key?(task_metadata, :initial_call)
     assert process_metadata[:initial_call] == {Logger.TranslatorTest, :task, 1}
@@ -332,6 +334,7 @@
   test "translates Task async_stream crashes with neighbour" do
     fun = fn -> Task.async_stream([:oops], :erlang, :error, []) |> 
Enum.to_list() end
     {:ok, pid} = Task.start(__MODULE__, :task, [self(), fun])
+    parent = self()
 
     assert capture_log(:debug, fn ->
              ref = Process.monitor(pid)
@@ -345,12 +348,15 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [pid, parent] == task_metadata[:callers]
 
     assert {:oops, [_ | _]} = task_metadata[:crash_reason]
     assert {%ErlangError{original: :oops}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
   test "translates Task undef module crash" do
+    parent = self()
+
     assert capture_log(fn ->
              {:ok, pid} = Task.start(:module_does_not_exist, :undef, [])
              ref = Process.monitor(pid)
@@ -365,12 +371,15 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [parent] == task_metadata[:callers]
 
     assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
   test "translates Task undef function crash" do
+    parent = self()
+
     assert capture_log(fn ->
              {:ok, pid} = Task.start(__MODULE__, :undef, [])
              ref = Process.monitor(pid)
@@ -385,12 +394,15 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [parent] == task_metadata[:callers]
 
     assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%UndefinedFunctionError{function: :undef}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
   test "translates Task raising ErlangError" do
+    parent = self()
+
     assert capture_log(fn ->
              exception =
                try do
@@ -413,12 +425,15 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [parent] == task_metadata[:callers]
 
     assert {%ErlangError{original: :foo}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%ErlangError{original: :foo}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
   test "translates Task raising Erlang badarg error" do
+    parent = self()
+
     assert capture_log(fn ->
              {:ok, pid} = Task.start(:erlang, :error, [:badarg])
              ref = Process.monitor(pid)
@@ -433,12 +448,15 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [parent] == task_metadata[:callers]
 
     assert {%ArgumentError{message: "argument error"}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%ArgumentError{message: "argument error"}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
   test "translates Task exiting abnormally" do
+    parent = self()
+
     assert capture_log(fn ->
              {:ok, pid} = Task.start(:erlang, :exit, [:abnormal])
              ref = Process.monitor(pid)
@@ -453,6 +471,7 @@
 
     assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
     assert_receive {:error, _pid, {Logger, ["Process " | _], _ts, 
process_metadata}}
+    assert [parent] == task_metadata[:callers]
 
     assert {:abnormal, [_ | _]} = task_metadata[:crash_reason]
     assert {:abnormal, [_ | _]} = process_metadata[:crash_reason]
@@ -625,8 +644,9 @@
            """
   end
 
-  test "translates :proc_lib crashes on debug" do
+  test "translates :proc_lib+Task crashes on debug" do
     {:ok, pid} = Task.start_link(__MODULE__, :task, [self()])
+    parent = self()
 
     assert capture_log(:debug, fn ->
              ref = Process.monitor(pid)
@@ -652,13 +672,15 @@
     assert process_metadata[:pid] == task_metadata[:pid]
     assert is_list(process_metadata[:callers])
     assert is_list(process_metadata[:ancestors])
+    assert [parent] == task_metadata[:callers]
 
     assert {%RuntimeError{message: "oops"}, [_ | _]} = 
task_metadata[:crash_reason]
     assert {%RuntimeError{message: "oops"}, [_ | _]} = 
process_metadata[:crash_reason]
   end
 
-  test "translates :proc_lib crashes with neighbour on debug" do
+  test "translates :proc_lib+Task crashes with neighbour on debug" do
     {:ok, pid} = Task.start_link(__MODULE__, :sub_task, [self()])
+    parent = self()
 
     assert capture_log(:debug, fn ->
              ref = Process.monitor(pid)
@@ -677,6 +699,9 @@
                    Current Stacktrace:
                        (lib/logger/)?test/logger/translator_test.exs:\d+: 
Logger.TranslatorTest.sleep/1
            """
+
+    assert_receive {:error, _pid, {Logger, ["Task " <> _ | _], _ts, 
task_metadata}}
+    assert [parent] == task_metadata[:callers]
   end
 
   test "translates Supervisor progress" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/local.ex 
new/elixir-1.10.4/lib/mix/lib/mix/local.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/local.ex  2020-04-25 10:30:20.000000000 
+0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/local.ex  2020-07-04 13:10:47.000000000 
+0200
@@ -161,14 +161,29 @@
         contents
 
       {:remote, message} ->
-        Mix.raise("""
-        #{message}
+        Mix.raise(
+          """
+          #{message}
 
-        Could not install #{name} because Mix could not download metadata at 
#{path}.
-        """)
+          Could not install #{name} because Mix could not download metadata at 
#{path}.
+          """ <> suggestions(name)
+        )
     end
   end
 
+  defp suggestions("Hex") do
+    """
+
+    Alternatively, you can compile and install Hex directly with this command:
+
+        mix archive.install github hexpm/hex branch latest
+    """
+  end
+
+  defp suggestions(_) do
+    ""
+  end
+
   defp parse_csv(body) do
     body
     |> :binary.split("\n", [:global, :trim])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/release.ex 
new/elixir-1.10.4/lib/mix/lib/mix/release.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/release.ex        2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/release.ex        2020-07-04 
13:10:47.000000000 +0200
@@ -402,7 +402,7 @@
     args = [runtime_config?, sys_config]
     format = "%% coding: utf-8~n%% RUNTIME_CONFIG=~s~n~tw.~n"
     File.mkdir_p!(Path.dirname(path))
-    File.write!(path, :io_lib.format(format, args), [:utf8])
+    File.write!(path, IO.chardata_to_string(:io_lib.format(format, args)))
 
     case :file.consult(path) do
       {:ok, _} ->
@@ -512,7 +512,7 @@
           :ok | {:error, String.t()}
   def make_boot_script(release, path, modes, prepend_paths \\ []) do
     with {:ok, rel_spec} <- build_release_spec(release, modes) do
-      File.write!(path <> ".rel", consultable(rel_spec), [:utf8])
+      File.write!(path <> ".rel", consultable(rel_spec))
 
       sys_path = String.to_charlist(path)
 
@@ -535,7 +535,7 @@
             |> prepend_paths_to_script(prepend_paths)
 
           script = {:script, rel_info, instructions}
-          File.write!(script_path, consultable(script), [:utf8])
+          File.write!(script_path, consultable(script))
           :ok = :systools.script2boot(sys_path)
 
         {:error, module, info} ->
@@ -657,7 +657,7 @@
   end
 
   defp consultable(term) do
-    :io_lib.format("%% coding: utf-8~n~tp.~n", [term])
+    IO.chardata_to_string(:io_lib.format("%% coding: utf-8~n~tp.~n", [term]))
   end
 
   @doc """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/shell.ex 
new/elixir-1.10.4/lib/mix/lib/mix/shell.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/shell.ex  2020-04-25 10:30:20.000000000 
+0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/shell.ex  2020-07-04 13:10:47.000000000 
+0200
@@ -76,8 +76,12 @@
 
   ## Options
 
+    * `:cd` - (since v1.11.0) the directory to run the command in
+
     * `:stderr_to_stdout` - redirects stderr to stdout, defaults to true
+
     * `:env` - a list of environment variables, defaults to `[]`
+
     * `:quiet` - overrides the callback to no-op
 
   """
@@ -98,7 +102,10 @@
         []
       end
 
-    opts = [:stream, :binary, :exit_status, :hide, :use_stdio, {:env, env} | 
args]
+    opts =
+      [:stream, :binary, :exit_status, :hide, :use_stdio, {:env, env}] ++
+        args ++ Keyword.take(options, [:cd])
+
     port = Port.open({:spawn, shell_command(command)}, opts)
     port_read(port, callback)
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/tasks/app.start.ex 
new/elixir-1.10.4/lib/mix/lib/mix/tasks/app.start.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/tasks/app.start.ex        2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/tasks/app.start.ex        2020-07-04 
13:10:47.000000000 +0200
@@ -162,8 +162,8 @@
             {:error, {:file.format_error(:enoent), name}}
 
           path ->
-            case :file.consult(path) do
-              {:ok, [{:application, _, properties} = application_data]} ->
+            case consult_app_file_maybe_in_archive(path) do
+              {:ok, {:application, _, properties} = application_data} ->
                 with :ok <- :application.load(application_data) do
                   if compile_env = validate_compile_env? && 
properties[:compile_env] do
                     # Unfortunately we can only check the current app here,
@@ -182,6 +182,19 @@
     end
   end
 
+  defp consult_app_file_maybe_in_archive(path) do
+    # The path could be located in .ez archive
+    case :erl_prim_loader.get_file(path) do
+      {:ok, bin, _full_name} ->
+        with {:ok, tokens, _} <- :erl_scan.string(String.to_charlist(bin)) do
+          :erl_parse.parse_term(tokens)
+        end
+
+      :error ->
+        {:error, :enoent}
+    end
+  end
+
   @doc false
   def type(config, opts) do
     cond do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/tasks/cmd.ex 
new/elixir-1.10.4/lib/mix/lib/mix/tasks/cmd.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/tasks/cmd.ex      2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/tasks/cmd.ex      2020-07-04 
13:10:47.000000000 +0200
@@ -22,6 +22,13 @@
   This task is automatically reenabled, so it can be called multiple times
   with different arguments.
 
+  ## Command line options
+
+    * `--app` - limit running the command to the given app. This option
+      may be given multiple times
+
+    * `--cd` - (since v1.11.0) the directory to run the command in
+
   ## Zombie operating system processes
 
   Beware that the Erlang VM does not terminate child processes
@@ -35,12 +42,20 @@
   of the `Port` module documentation.
   """
 
+  @switches [
+    app: :keep,
+    cd: :string
+  ]
+
   @impl true
   def run(args) do
-    {args, apps} = parse_apps(args, [])
+    {opts, args} = OptionParser.parse_head!(args, strict: @switches)
+    apps = Enum.map(List.wrap(opts[:app]), &String.to_atom/1)
 
     if apps == [] or Mix.Project.config()[:app] in apps do
-      case Mix.shell().cmd(Enum.join(args, " ")) do
+      cmd_opts = Keyword.take(opts, [:cd])
+
+      case Mix.shell().cmd(Enum.join(args, " "), cmd_opts) do
         0 -> :ok
         status -> exit(status)
       end
@@ -48,14 +63,4 @@
 
     Mix.Task.reenable("cmd")
   end
-
-  defp parse_apps(args, apps) do
-    case args do
-      ["--app", app | tail] ->
-        parse_apps(tail, [String.to_atom(app) | apps])
-
-      args ->
-        {args, apps}
-    end
-  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/lib/mix/tasks/local.hex.ex 
new/elixir-1.10.4/lib/mix/lib/mix/tasks/local.hex.ex
--- old/elixir-1.10.3/lib/mix/lib/mix/tasks/local.hex.ex        2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/lib/mix/tasks/local.hex.ex        2020-07-04 
13:10:47.000000000 +0200
@@ -11,6 +11,11 @@
 
       mix local.hex
 
+  If installing a precompiled Hex does not work, you can compile and install
+  Hex directly with this command:
+
+      mix archive.install github hexpm/hex branch latest
+
   ## Command line options
 
     * `--force` - forces installation without a shell prompt; primarily
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/mix/test/fixtures/release_test/config/config.exs 
new/elixir-1.10.4/lib/mix/test/fixtures/release_test/config/config.exs
--- old/elixir-1.10.3/lib/mix/test/fixtures/release_test/config/config.exs      
2020-04-25 10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/fixtures/release_test/config/config.exs      
2020-07-04 13:10:47.000000000 +0200
@@ -1,4 +1,4 @@
 import Config
 
 config :release_test, :static, :was_set
-config :release_test, :encoding, {:"£", "£", '£'}
+config :release_test, :encoding, {:time_μs, :"£", "£", '£'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/test/mix/release_test.exs 
new/elixir-1.10.4/lib/mix/test/mix/release_test.exs
--- old/elixir-1.10.3/lib/mix/test/mix/release_test.exs 2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/mix/release_test.exs 2020-07-04 
13:10:47.000000000 +0200
@@ -488,11 +488,15 @@
     end
 
     test "writes sys_config with encoding" do
-      assert make_sys_config(release([]), [encoding: {:"£", "£", '£'}], 
"unused/runtime/path") ==
+      assert make_sys_config(
+               release([]),
+               [encoding: {:time_μs, :"£", "£", '£'}],
+               "unused/runtime/path"
+             ) ==
                :ok
 
       {:ok, contents} = :file.consult(@sys_config)
-      assert contents == [[encoding: {:"£", "£", '£'}]]
+      assert contents == [[encoding: {:time_μs, :"£", "£", '£'}]]
     end
 
     test "writes the given sys_config with config providers" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/test/mix/shell_test.exs 
new/elixir-1.10.4/lib/mix/test/mix/shell_test.exs
--- old/elixir-1.10.3/lib/mix/test/mix/shell_test.exs   2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/mix/shell_test.exs   2020-07-04 
13:10:47.000000000 +0200
@@ -17,4 +17,16 @@
   after
     Mix.shell(Mix.Shell.Process)
   end
+
+  test "with :cd" do
+    Mix.shell(Mix.Shell.IO)
+    tmp_dir = System.tmp_dir()
+    {pwd, 0} = System.cmd("pwd", [], cd: tmp_dir)
+
+    assert ExUnit.CaptureIO.capture_io(fn ->
+             Mix.shell().cmd("pwd", cd: tmp_dir)
+           end) == pwd
+  after
+    Mix.shell(Mix.Shell.Process)
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/elixir-1.10.3/lib/mix/test/mix/tasks/cmd_test.exs 
new/elixir-1.10.4/lib/mix/test/mix/tasks/cmd_test.exs
--- old/elixir-1.10.3/lib/mix/test/mix/tasks/cmd_test.exs       2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/mix/tasks/cmd_test.exs       2020-07-04 
13:10:47.000000000 +0200
@@ -36,4 +36,16 @@
       end)
     end)
   end
+
+  test "only runs the cmd for specified apps and in specific directory" do
+    in_fixture("umbrella_dep/deps/umbrella", fn ->
+      Mix.Project.in_project(:umbrella, ".", fn _ ->
+        Mix.Task.run("cmd", ["--app", "bar", "--cd", "lib", "pwd"])
+        assert_received {:mix_shell, :info, ["==> bar"]}
+        {pwd, 0} = System.cmd("pwd", [], cd: Path.join(["apps", "bar", "lib"]))
+        assert_received {:mix_shell, :run, [^pwd]}
+        refute_received {:mix_shell, :info, ["==> foo"]}
+      end)
+    end)
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/mix/test/mix/tasks/compile_test.exs 
new/elixir-1.10.4/lib/mix/test/mix/tasks/compile_test.exs
--- old/elixir-1.10.3/lib/mix/test/mix/tasks/compile_test.exs   2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/mix/tasks/compile_test.exs   2020-07-04 
13:10:47.000000000 +0200
@@ -146,6 +146,39 @@
     end)
   end
 
+  test "calling raise inside a macro returns a diagnostic with a position" do
+    in_fixture("no_mixfile", fn ->
+      File.write!("lib/a.ex", """
+      defmodule A do
+        defmacro custom_macro do
+          raise "error"
+        end
+      end
+      """)
+
+      File.write!("lib/b.ex", """
+      defmodule B do
+        require A
+        A.custom_macro()
+      end
+      """)
+
+      file = Path.absname("lib/b.ex")
+
+      ExUnit.CaptureIO.capture_io(fn ->
+        assert {:error, [diagnostic]} = Mix.Task.run("compile", 
["--return-errors"])
+
+        assert %Mix.Task.Compiler.Diagnostic{
+                 file: ^file,
+                 severity: :error,
+                 position: 3,
+                 message: "** (RuntimeError) error\n    expanding macro: 
A.custom_macro/0" <> _,
+                 compiler_name: "Elixir"
+               } = diagnostic
+      end)
+    end)
+  end
+
   test "returns syntax error from an Erlang file when --return-errors is set" 
do
     in_fixture("no_mixfile", fn ->
       import ExUnit.CaptureIO
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/elixir-1.10.3/lib/mix/test/mix/tasks/release_test.exs 
new/elixir-1.10.4/lib/mix/test/mix/tasks/release_test.exs
--- old/elixir-1.10.3/lib/mix/test/mix/tasks/release_test.exs   2020-04-25 
10:30:20.000000000 +0200
+++ new/elixir-1.10.4/lib/mix/test/mix/tasks/release_test.exs   2020-07-04 
13:10:47.000000000 +0200
@@ -281,7 +281,7 @@
         assert %{
                  app_dir: app_dir,
                  cookie_env: ^cookie,
-                 encoding: {:"£", "£", '£'},
+                 encoding: {:time_μs, :"£", "£", '£'},
                  mode: :embedded,
                  node: release_node("release_test"),
                  protocols_consolidated?: true,
@@ -322,7 +322,7 @@
         File.write!("config/releases.exs", """
         import Config
         config :release_test, :runtime, :was_set
-        config :release_test, :encoding, {:runtime, :"£", "£", '£'}
+        config :release_test, :encoding, {:runtime, :time_μs, :"£", "£", '£'}
         """)
 
         root = Path.absname("_build/dev/rel/runtime_config")
@@ -348,7 +348,7 @@
         open_port(Path.join(root, "bin/runtime_config"), ['start'])
 
         assert %{
-                 encoding: {:runtime, :"£", "£", '£'},
+                 encoding: {:runtime, :time_μs, :"£", "£", '£'},
                  mode: :embedded,
                  node: release_node("runtime_config"),
                  protocols_consolidated?: true,


Reply via email to