Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: elixir-lang/elixir
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.13.3
Choose a base ref
...
head repository: elixir-lang/elixir
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.13.4
Choose a head ref
  • 17 commits
  • 35 files changed
  • 5 contributors

Commits on Feb 13, 2022

  1. Copy the full SHA
    39d8675 View commit details

Commits on Feb 14, 2022

  1. Add compile-time dependencies on require

    Projects like Plug use require to establish compile
    time dependencies inside a Plug. The fact require
    only added a compile-time dependency in v1.13.0 was
    therefore a regression, addressed by this commit.
    josevalim committed Feb 14, 2022
    Copy the full SHA
    bac5b1d View commit details
  2. @doc false URI.Error.message/1

    josevalim committed Feb 14, 2022
    Copy the full SHA
    1e4ed32 View commit details

Commits on Feb 17, 2022

  1. Copy the full SHA
    bb17204 View commit details
  2. Update Mix.TasksTestTest for Erlang/OTP 25 (#11637)

    The order in which tests get executed can be different
    depending on Erlang/OTP version
    
    The test failure was:
    
        1) test logs and errors umbrella with file path (Mix.Tasks.TestTest)
           test/mix/tasks/test_test.exs:432
           Assertion with =~ failed
           code:  assert mix(["test", "apps/unknown_app/test"]) =~
                    "==> bar\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n==> foo\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n"
           left:  "==> foo\nCompiling 1 file (.ex)\nGenerated foo app\n==> bar\nCompiling 1 file (.ex)\nGenerated bar app\n==> foo\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n==> bar\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n"
           right: "==> bar\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n==> foo\nPaths given to \"mix test\" did not match any directory/file: apps/unknown_app/test\n"
           stacktrace:
             test/mix/tasks/test_test.exs:436: anonymous fn/0 in Mix.Tasks.TestTest."test logs and errors umbrella with file path"/1
             (elixir 1.14.0-dev) lib/file.ex:1555: File.cd!/2
             test/test_helper.exs:127: MixTest.Case.in_fixture/3
             test/mix/tasks/test_test.exs:433: (test)
    michallepicki authored and josevalim committed Feb 17, 2022
    Copy the full SHA
    ee6ed75 View commit details
  3. Update Mix.DepTest for Erlang/OTP 25 (#11636)

    :digraph_utils.topsort/1 can return a different (but also valid)
    topological ordering
    
    The test failure on Erlang/OTP 25.0-rc1 was:
    
        1) test deps_paths (Mix.DepTest)
           test/mix/dep_test.exs:491
           Assertion with == failed
           code:  assert Enum.map(Mix.Dep.load_on_environment([]), & &1.app) == [:git_repo, :abc_repo, :deps_repo]
           left:  [:abc_repo, :git_repo, :deps_repo]
           right: [:git_repo, :abc_repo, :deps_repo]
           stacktrace:
             test/mix/dep_test.exs:499: anonymous fn/0 in Mix.DepTest."test deps_paths"/1
             (elixir 1.14.0-dev) lib/file.ex:1555: File.cd!/2
             test/test_helper.exs:127: MixTest.Case.in_fixture/3
             test/mix/dep_test.exs:31: Mix.DepTest.with_deps/2
             test/mix/dep_test.exs:497: (test)
    michallepicki authored and josevalim committed Feb 17, 2022
    Copy the full SHA
    f809d03 View commit details
  4. Copy the full SHA
    4b480cb View commit details
  5. Copy the full SHA
    c028c2d View commit details
  6. Deprecate rebar2

    josevalim committed Feb 17, 2022
    Copy the full SHA
    63d682b View commit details
  7. Skip tests using Rebar2 on Erlang/OTP 25+ (#11643)

    * Skip tests using Rebar2 on Erlang/OTP 25+
    
    and clean up mix test_helper.exs exclude filters
    
    * Remove unnecessary printing from mix test_helper.exs exclude filters
    michallepicki authored and josevalim committed Feb 17, 2022
    Copy the full SHA
    65681b8 View commit details
  8. Update local rebar3

    josevalim committed Feb 17, 2022
    Copy the full SHA
    fe43e23 View commit details
  9. Copy the full SHA
    67cf14c View commit details

Commits on Feb 28, 2022

  1. Copy the full SHA
    89e5788 View commit details

Commits on Mar 19, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f950226 View commit details

Commits on Mar 25, 2022

  1. Copy the full SHA
    e0c8b8a View commit details

Commits on Apr 6, 2022

  1. Copy the full SHA
    d52f533 View commit details

Commits on Apr 7, 2022

  1. Release v1.13.4

    josevalim committed Apr 7, 2022
    Copy the full SHA
    7e4fbe6 View commit details
Showing with 261 additions and 119 deletions.
  1. +1 −1 .github/workflows/ci.yml
  2. +25 −0 CHANGELOG.md
  3. +1 −0 Makefile
  4. +1 −1 VERSION
  5. +1 −1 bin/elixir
  6. +1 −1 bin/elixir.bat
  7. +1 −1 lib/elixir/lib/base.ex
  8. +5 −4 lib/elixir/lib/code/formatter.ex
  9. +10 −9 lib/elixir/lib/kernel/lexical_tracker.ex
  10. +3 −2 lib/elixir/lib/kernel/special_forms.ex
  11. +2 −1 lib/elixir/lib/module.ex
  12. +4 −4 lib/elixir/lib/module/types/unify.ex
  13. +4 −0 lib/elixir/lib/registry.ex
  14. +1 −0 lib/elixir/lib/uri.ex
  15. +1 −1 lib/elixir/src/elixir_expand.erl
  16. +2 −2 lib/elixir/src/elixir_lexical.erl
  17. +22 −15 lib/elixir/test/elixir/code_formatter/general_test.exs
  18. +14 −12 lib/elixir/test/elixir/code_test.exs
  19. +23 −10 lib/elixir/test/elixir/kernel/lexical_tracker_test.exs
  20. +1 −2 lib/elixir/test/elixir/module/locals_tracker_test.exs
  21. +48 −16 lib/elixir/test/elixir/module/types/types_test.exs
  22. +10 −10 lib/elixir/test/elixir/module/types/unify_test.exs
  23. +14 −0 lib/elixir/test/elixir/registry_test.exs
  24. +9 −0 lib/mix/lib/mix/dep/loader.ex
  25. +7 −4 lib/mix/lib/mix/tasks/xref.ex
  26. +1 −0 lib/mix/test/fixtures/.gitignore
  27. BIN lib/mix/test/fixtures/archive/ebin/Elixir.Mix.Tasks.Local.Sample.beam
  28. +0 −3 lib/mix/test/fixtures/archive/ebin/local_sample.app
  29. BIN lib/mix/test/fixtures/rebar3
  30. +5 −2 lib/mix/test/mix/dep_test.exs
  31. +5 −3 lib/mix/test/mix/rebar_test.exs
  32. +6 −1 lib/mix/test/mix/tasks/test_test.exs
  33. +6 −7 lib/mix/test/mix/tasks/xref_test.exs
  34. +1 −1 lib/mix/test/mix/umbrella_test.exs
  35. +26 −5 lib/mix/test/test_helper.exs
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
otp_release: ['OTP-24.0', 'OTP-23.3', 'OTP-23.0', 'OTP-22.3', 'OTP-22.0']
otp_release: ['OTP-24.3', 'OTP-24.0', 'OTP-23.3', 'OTP-23.0', 'OTP-22.3', 'OTP-22.0']
development: [false]
include:
- otp_release: master
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -128,6 +128,31 @@ Now any application can use your formatter as follows:

Finally, the `Code` module has also been augmented with two functions: `Code.string_to_quoted_with_comments/2` and `Code.quoted_to_algebra/2`. Those functions allow someone to retrieve the Elixir AST with their original source code comments, and then convert this AST to formatted code. In other words, those functions provide a wrapper around the Elixir Code Formatter, supporting developers who wish to create tools that directly manipulate and custom format Elixir source code.

## v1.13.4 (2022-04-07)

This release has been verified to work with Erlang/OTP 25 RC2.

### 1. Enhancements

#### Elixir

* [Code] Allow iodata to be returned in sigil formatting functions
* [Code] Pass opening delimiter information to sigil formatting functions

### 2. Bug fixes

#### Elixir

* [Kernel] Tweak type unification to fix infinite loop with recursive vars
* [Kernel] Add compile-time dependencies on `require`
* [Registry] Make `Registry` send work with named triplets

### 3. Deprecations

#### Mix

* [mix rebar] Deprecate Rebar 2 as it no longer works on Erlang/OTP 25

## v1.13.3 (2022-02-09)

### 1. Enhancements
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -171,6 +171,7 @@ clean_residual_files:
rm -rf lib/mix/test/fixtures/git_rebar/
rm -rf lib/mix/test/fixtures/git_repo/
rm -rf lib/mix/test/fixtures/git_sparse_repo/
rm -rf lib/mix/test/fixtures/archive/ebin/
rm -f erl_crash.dump
$(Q) $(MAKE) clean_man

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.13.3
1.13.4
2 changes: 1 addition & 1 deletion bin/elixir
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
set -e

ELIXIR_VERSION=1.13.3
ELIXIR_VERSION=1.13.4

if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
cat <<USAGE >&2
2 changes: 1 addition & 1 deletion bin/elixir.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)

set ELIXIR_VERSION=1.13.3
set ELIXIR_VERSION=1.13.4

setlocal enabledelayedexpansion
if ""%1""=="""" if ""%2""=="""" goto documentation
2 changes: 1 addition & 1 deletion lib/elixir/lib/base.ex
Original file line number Diff line number Diff line change
@@ -340,7 +340,7 @@ defmodule Base do
"foobar"
"""
@spec decode16!(binary, case: encode_case) :: binary
@spec decode16!(binary, case: decode_case) :: binary
def decode16!(string, opts \\ [])

def decode16!(string, opts) when is_binary(string) and rem(byte_size(string), 2) == 0 do
9 changes: 5 additions & 4 deletions lib/elixir/lib/code/formatter.ex
Original file line number Diff line number Diff line change
@@ -1326,16 +1326,17 @@ defmodule Code.Formatter do
file: state.file,
line: meta[:line],
sigil: List.to_atom([name]),
modifiers: modifiers
modifiers: modifiers,
opening_delimiter: opening_delimiter
]

case callback.(hd(entries), metadata) do
binary when is_binary(binary) ->
[binary]
iodata when is_binary(iodata) or is_list(iodata) ->
[IO.iodata_to_binary(iodata)]

other ->
raise ArgumentError,
"expected sigil callback to return a binary, got: #{inspect(other)}"
"expected sigil callback to return iodata, got: #{inspect(other)}"
end

%{} ->
19 changes: 10 additions & 9 deletions lib/elixir/lib/kernel/lexical_tracker.ex
Original file line number Diff line number Diff line change
@@ -30,8 +30,8 @@ defmodule Kernel.LexicalTracker do
end

@doc false
def add_require(pid, module) when is_atom(module) do
:gen_server.cast(pid, {:add_require, module})
def add_export(pid, module) when is_atom(module) do
:gen_server.cast(pid, {:add_export, module})
end

@doc false
@@ -168,15 +168,16 @@ defmodule Kernel.LexicalTracker do
{:noreply, update_in(state.compile_env, &:ordsets.add_element({app, path, return}, &1))}
end

def handle_cast({:add_require, module}, state) do
def handle_cast({:add_export, module}, state) do
{:noreply, put_in(state.exports[module], true)}
end

def handle_cast({:add_import, module, fas, line, warn}, state) do
to_remove = for {{:import, {^module, _, _}} = key, _} <- state.directives, do: key
%{directives: directives, exports: exports} = state
to_remove = for {{:import, {^module, _, _}} = key, _} <- directives, do: key

directives =
state.directives
directives
|> Map.drop(to_remove)
|> add_directive(module, line, warn, :import)

@@ -185,7 +186,7 @@ defmodule Kernel.LexicalTracker do
add_directive(directives, {module, function, arity}, line, warn, :import)
end)

{:noreply, %{state | directives: directives}}
{:noreply, %{state | directives: directives, exports: Map.put(exports, module, true)}}
end

def handle_cast({:add_alias, module, line, warn}, state) do
@@ -221,9 +222,9 @@ defmodule Kernel.LexicalTracker do
do: Map.put(references, module, :compile)

defp add_reference(references, module, :runtime) when is_atom(module) do
case Map.fetch(references, module) do
{:ok, _} -> references
:error -> Map.put(references, module, :runtime)
case references do
%{^module => _} -> references
_ -> Map.put(references, module, :runtime)
end
end

5 changes: 3 additions & 2 deletions lib/elixir/lib/kernel/special_forms.ex
Original file line number Diff line number Diff line change
@@ -554,7 +554,9 @@ defmodule Kernel.SpecialForms do
defmacro alias(module, opts), do: error!([module, opts])

@doc """
Requires a module in order to use its macros.
Requires a module as a compile-time dependency.
Requiring a module is necessary in order to use its macros.
## Examples
@@ -576,7 +578,6 @@ defmodule Kernel.SpecialForms do
`require/2` also accepts `:as` as an option so it automatically sets
up an alias. Please check `alias/2` for more information.
"""
defmacro require(module, opts), do: error!([module, opts])

3 changes: 2 additions & 1 deletion lib/elixir/lib/module.ex
Original file line number Diff line number Diff line change
@@ -1811,7 +1811,8 @@ defmodule Module do
acc

true ->
:elixir_env.trace({:require, [], behaviour, []}, env)
event = {:remote_function, [], behaviour, :behaviour_info, 1}
:elixir_env.trace(event, %{env | function: {:__info__, 1}})
optional_callbacks = behaviour_info(behaviour, :optional_callbacks)
callbacks = behaviour_info(behaviour, :callbacks)
Enum.reduce(callbacks, acc, &add_callback(&1, behaviour, env, optional_callbacks, &2))
8 changes: 4 additions & 4 deletions lib/elixir/lib/module/types/unify.ex
Original file line number Diff line number Diff line change
@@ -43,14 +43,14 @@ defmodule Module.Types.Unify do
{:ok, same, context}
end

def unify(type, {:var, var}, stack, context) do
unify_var(var, type, stack, context, _var_source = false)
end

def unify({:var, var}, type, stack, context) do
unify_var(var, type, stack, context, _var_source = true)
end

def unify(type, {:var, var}, stack, context) do
unify_var(var, type, stack, context, _var_source = false)
end

def unify({:tuple, n, sources}, {:tuple, n, targets}, stack, context) do
result =
map_reduce_ok(Enum.zip(sources, targets), context, fn {source, target}, context ->
4 changes: 4 additions & 0 deletions lib/elixir/lib/registry.ex
Original file line number Diff line number Diff line change
@@ -260,6 +260,10 @@ defmodule Registry do
end
end

def send({registry, key, _value}, msg) do
Registry.send({registry, key}, msg)
end

@doc false
def unregister_name({registry, key}), do: unregister(registry, key)
def unregister_name({registry, key, _value}), do: unregister(registry, key)
1 change: 1 addition & 0 deletions lib/elixir/lib/uri.ex
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ defmodule URI do
defmodule Error do
defexception [:action, :reason, :part]

@doc false
def message(%Error{action: action, reason: reason, part: part}) do
"cannot #{action} due to reason #{reason}: #{inspect(part)}"
end
2 changes: 1 addition & 1 deletion lib/elixir/src/elixir_expand.erl
Original file line number Diff line number Diff line change
@@ -85,6 +85,7 @@ expand({require, Meta, [Ref, Opts]}, S, E) ->
if
is_atom(ERef) ->
elixir_aliases:ensure_loaded(Meta, ERef, ET),
elixir_env:trace({require, Meta, ERef, EOpts}, ET),
{ERef, ST, expand_require(Meta, ERef, EOpts, ET)};
true ->
form_error(Meta, E, ?MODULE, {expected_compile_time_module, require, Ref})
@@ -931,7 +932,6 @@ no_alias_expansion(Other) ->
Other.

expand_require(Meta, Ref, Opts, E) ->
elixir_env:trace({require, Meta, Ref, Opts}, E),
RE = E#{requires := ordsets:add_element(Ref, ?key(E, requires))},
expand_alias(Meta, false, Ref, Opts, RE).

4 changes: 2 additions & 2 deletions lib/elixir/src/elixir_lexical.erl
Original file line number Diff line number Diff line change
@@ -47,10 +47,10 @@ trace({alias_expansion, _Meta, Lookup, _Result}, #{lexical_tracker := Pid}) ->
?tracker:alias_dispatch(Pid, Lookup),
ok;
trace({require, _Meta, Module, _Opts}, #{lexical_tracker := Pid}) ->
?tracker:add_require(Pid, Module),
?tracker:remote_dispatch(Pid, Module, compile),
ok;
trace({struct_expansion, _Meta, Module, _Keys}, #{lexical_tracker := Pid}) ->
?tracker:add_require(Pid, Module),
?tracker:add_export(Pid, Module),
ok;
trace({alias_reference, _Meta, Module}, #{lexical_tracker := Pid} = E) ->
?tracker:remote_dispatch(Pid, Module, mode(E)),
37 changes: 22 additions & 15 deletions lib/elixir/test/elixir/code_formatter/general_test.exs
Original file line number Diff line number Diff line change
@@ -126,23 +126,23 @@ defmodule Code.Formatter.GeneralTest do
"""

formatter = fn content, opts ->
assert opts == [file: nil, line: 1, sigil: :W, modifiers: []]
assert opts == [file: nil, line: 1, sigil: :W, modifiers: [], opening_delimiter: "/"]
content |> String.split(~r/ +/) |> Enum.join(" ")
end

assert_format bad, good, sigils: [W: formatter]

bad = """
var = ~W/foo bar baz/abc
var = ~W<foo bar baz>abc
"""

good = """
var = ~W/foo bar baz/abc
var = ~W<foo bar baz>abc
"""

formatter = fn content, opts ->
assert opts == [file: nil, line: 1, sigil: :W, modifiers: 'abc']
content |> String.split(~r/ +/) |> Enum.join(" ")
assert opts == [file: nil, line: 1, sigil: :W, modifiers: 'abc', opening_delimiter: "<"]
content |> String.split(~r/ +/) |> Enum.intersperse(" ")
end

assert_format bad, good, sigils: [W: formatter]
@@ -162,34 +162,41 @@ defmodule Code.Formatter.GeneralTest do
"""

formatter = fn content, opts ->
assert opts == [file: nil, line: 1, sigil: :W, modifiers: []]
assert opts == [file: nil, line: 1, sigil: :W, modifiers: [], opening_delimiter: "'''"]
content |> String.split(~r/ +/) |> Enum.join(" ")
end

assert_format bad, good, sigils: [W: formatter]

bad = """
bad = ~S'''
if true do
~W'''
~W"""
foo
bar
baz
'''abc
"""abc
end
"""
'''

good = """
good = ~S'''
if true do
~W'''
~W"""
foo
bar
baz
'''abc
"""abc
end
"""
'''

formatter = fn content, opts ->
assert opts == [file: nil, line: 2, sigil: :W, modifiers: 'abc']
assert opts == [
file: nil,
line: 2,
sigil: :W,
modifiers: 'abc',
opening_delimiter: ~S/"""/
]

content |> String.split(~r/ +/) |> Enum.join("\n")
end

26 changes: 14 additions & 12 deletions lib/elixir/test/elixir/code_test.exs
Original file line number Diff line number Diff line change
@@ -78,18 +78,20 @@ defmodule CodeTest do
end
end

test "raises streamlined argument errors" do
assert_raise ArgumentError,
~r"argument error while evaluating at line 1",
fn -> Code.eval_string("a <> b", a: :a, b: :b) end

assert_raise ArgumentError,
~r"argument error while evaluating example.ex at line 1",
fn -> Code.eval_string("a <> b", [a: :a, b: :b], file: "example.ex") end

assert_raise ArgumentError,
~r"argument error while evaluating example.ex between lines 1 and 2",
fn -> Code.eval_string("a <>\nb", [a: :a, b: :b], file: "example.ex") end
if System.otp_release() < "25" do
test "raises streamlined argument errors" do
assert_raise ArgumentError,
~r"argument error while evaluating at line 1",
fn -> Code.eval_string("a <> b", a: :a, b: :b) end

assert_raise ArgumentError,
~r"argument error while evaluating example.ex at line 1",
fn -> Code.eval_string("a <> b", [a: :a, b: :b], file: "example.ex") end

assert_raise ArgumentError,
~r"argument error while evaluating example.ex between lines 1 and 2",
fn -> Code.eval_string("a <>\nb", [a: :a, b: :b], file: "example.ex") end
end
end
end

Loading