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.15.5
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.15.6
Choose a head ref
  • 12 commits
  • 30 files changed
  • 3 contributors

Commits on Aug 30, 2023

  1. Copy the full SHA
    119580f View commit details

Commits on Sep 4, 2023

  1. Copy the full SHA
    138b442 View commit details

Commits on Sep 11, 2023

  1. Copy the full SHA
    e4e2f1a View commit details

Commits on Sep 12, 2023

  1. Copy the full SHA
    b1a1dd0 View commit details
  2. Copy the full SHA
    e975613 View commit details
  3. Copy the full SHA
    fadf5c6 View commit details

Commits on Sep 13, 2023

  1. Copy the full SHA
    f1a5e6a View commit details
  2. Copy the full SHA
    2fe5b77 View commit details
  3. Copy the full SHA
    e30f8df View commit details

Commits on Sep 14, 2023

  1. Copy the full SHA
    6654f1b View commit details

Commits on Sep 20, 2023

  1. Improve Windows Installer (#12945)

    1. If we couldn't verify installed OTP, don't quit but let user proceed with installing just Elixir
    
    2. When checking installed OTPs, pick the recent most installed. Previously we were picking the first one which was basically guaranteed to be too old.
    
    3. If we find an existing Elixir installation but it doesn't match the OTP version, offer to download the OTP version this Elixir installer was compiled against (which usually would be the newer version)
    
    4. Add "Verify Erlang/OTP" button which re-checks for installed OTP.
    
    Closes #12678.
    wojtekmach authored and josevalim committed Sep 20, 2023
    Copy the full SHA
    26136e5 View commit details
  2. Release v1.15.6

    josevalim committed Sep 20, 2023
    Copy the full SHA
    a16517e View commit details
27 changes: 25 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -117,6 +117,29 @@ in the long term.
See the new `Logger` documentation for more information on the
new features and on compatibility.

## v1.15.6 (2023-09-20)

This release also includes fixes to the Windows installer.

### 1. Bug fixes

#### EEx

* [EEx] Do not crash when printing tokenizer warnings

#### Elixir

* [Code] Fix formatter for nested `*` in bitstrings
* [Code] Improve feedback when an invalid block is given `Code.quoted_to_algebra/2`
* [Kernel] Trace functions before they are inlined

#### Mix

* [mix compile] Ensure `:extra_applications` declare in umbrella projects are loaded
* [mix deps.get] Do not check for invalid applications before deps.get
* [mix deps.update] Do not check for invalid applications before deps.update
* [mix format] Load plugins when invoking the formatter from an IDE

## v1.15.5 (2023-08-28)

### 1. Enhancements
@@ -152,7 +175,7 @@ new features and on compatibility.

#### Mix

* [mix archive.build] Disable protocol consolidation when building archiveson archive.install
* [mix archive.build] Disable protocol consolidation when building archives on archive.install
* [mix compile] Track removed files per local dependency (this addresses a bug where files depending on modules from path dependencies always recompiled)
* [mix release] Do not strip relevant chunks from Erlang/OTP 26

@@ -166,7 +189,7 @@ new features and on compatibility.

#### Mix

* [Mix] Allow to opt out of starting apps in `Mix.install/2`
* [Mix] Allow to opt-out of starting apps in `Mix.install/2`

### 2. Bug fixes

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.15.5
1.15.6
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.15.5
ELIXIR_VERSION=1.15.6

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.15.5
set ELIXIR_VERSION=1.15.6

setlocal enabledelayedexpansion
if ""%1""=="""" if ""%2""=="""" goto documentation
4 changes: 2 additions & 2 deletions lib/eex/lib/eex/compiler.ex
Original file line number Diff line number Diff line change
@@ -72,8 +72,8 @@ defmodule EEx.Compiler do
{key, expr} =
case :elixir_tokenizer.tokenize(expr, 1, file: "eex", check_terminators: false) do
{:ok, _line, _column, warnings, tokens} ->
Enum.each(Enum.reverse(warnings), fn {location, file, msg} ->
:elixir_errors.erl_warn(location, file, msg)
Enum.each(Enum.reverse(warnings), fn {location, msg} ->
:elixir_errors.erl_warn(location, state.file, msg)
end)

token_key(tokens, expr)
8 changes: 7 additions & 1 deletion lib/eex/test/eex/tokenizer_test.exs
Original file line number Diff line number Diff line change
@@ -5,7 +5,13 @@ defmodule EEx.TokenizerTest do

@opts [indentation: 0, trim: false]

test "simple chars lists" do
test "tokenizer warning" do
assert ExUnit.CaptureIO.capture_io(:stderr, fn ->
EEx.tokenize(~c"foo <% :'bar' %>", @opts)
end) =~ "found quoted atom \"bar\" but the quotes are not required"
end

test "simple charlists" do
assert EEx.tokenize(~c"foo", @opts) ==
{:ok, [{:text, ~c"foo", %{column: 1, line: 1}}, {:eof, %{column: 4, line: 1}}]}
end
61 changes: 55 additions & 6 deletions lib/elixir/lib/access.ex
Original file line number Diff line number Diff line change
@@ -191,9 +191,13 @@ defmodule Access do
case __STACKTRACE__ do
[unquote(top) | _] ->
reason =
"#{inspect(unquote(module))} does not implement the Access behaviour. " <>
"If you are using get_in/put_in/update_in, you can specify the field " <>
"to be accessed using Access.key!/1"
"""
#{inspect(unquote(module))} does not implement the Access behaviour
You can use the "struct.field" syntax to access struct fields. \
You can also use Access.key!/1 to access struct fields dynamically \
inside get_in/put_in/update_in\
"""

%{unquote(exception) | reason: reason}

@@ -326,9 +330,23 @@ defmodule Access do
end
end

def get(list, key, _default) when is_list(list) and is_integer(key) do
raise ArgumentError, """
the Access module does not support accessing lists by index, got: #{inspect(key)}
Accessing a list by index is typically discouraged in Elixir, \
instead we prefer to use the Enum module to manipulate lists \
as a whole. If you really must access a list element by index, \
you can Enum.at/1 or the functions in the List module\
"""
end

def get(list, key, _default) when is_list(list) do
raise ArgumentError,
"the Access calls for keywords expect the key to be an atom, got: " <> inspect(key)
raise ArgumentError, """
the Access module supports only keyword lists (with atom keys), got: #{inspect(key)}
If you want to search lists of tuples, use List.keyfind/3\
"""
end

def get(nil, _key, default) do
@@ -377,10 +395,26 @@ defmodule Access do
Map.get_and_update(map, key, fun)
end

def get_and_update(list, key, fun) when is_list(list) do
def get_and_update(list, key, fun) when is_list(list) and is_atom(key) do
Keyword.get_and_update(list, key, fun)
end

def get_and_update(list, key, _fun) when is_list(list) and is_integer(key) do
raise ArgumentError, """
the Access module does not support accessing lists by index, got: #{inspect(key)}
Accessing a list by index is typically discouraged in Elixir, \
instead we prefer to use the Enum module to manipulate lists \
as a whole. If you really must mostify a list element by index, \
you can Access.at/1 or the functions in the List module\
"""
end

def get_and_update(list, key, _fun) when is_list(list) do
raise ArgumentError,
"the Access module supports only keyword lists (with atom keys), got: " <> inspect(key)
end

def get_and_update(nil, key, _fun) do
raise ArgumentError, "could not put/update key #{inspect(key)} on a nil value"
end
@@ -507,6 +541,21 @@ defmodule Access do
iex> get_in(map, [Access.key!(:user), Access.key!(:unknown)])
** (KeyError) key :unknown not found in: %{name: \"john\"}
The examples above could be partially written as:
iex> map = %{user: %{name: "john"}}
iex> map.user.name
"john"
iex> get_and_update_in(map.user.name, fn prev ->
...> {prev, String.upcase(prev)}
...> end)
{"john", %{user: %{name: "JOHN"}}}
However, it is not possible to remove fields using the dot notation,
as it is implified those fields must also be present. In any case,
`Access.key!/1` is useful when the key is not known in advance
and must be accessed dynamically.
An error is raised if the accessed structure is not a map/struct:
iex> get_in([], [Access.key!(:foo)])
16 changes: 10 additions & 6 deletions lib/elixir/lib/code/formatter.ex
Original file line number Diff line number Diff line change
@@ -431,7 +431,7 @@ defmodule Code.Formatter do
{color("nil", nil, state.inspect_opts), state}
end

defp quoted_to_algebra({:__block__, meta, _} = block, _context, state) do
defp quoted_to_algebra({:__block__, meta, args} = block, _context, state) when is_list(args) do
{block, state} = block_to_algebra(block, line(meta), closing_line(meta), state)
{surround("(", block, ")"), state}
end
@@ -1419,7 +1419,9 @@ defmodule Code.Formatter do

defp bitstring_segment_to_algebra({{:"::", _, [segment, spec]}, i}, state, last) do
{doc, state} = quoted_to_algebra(segment, :parens_arg, state)
{spec, state} = bitstring_spec_to_algebra(spec, state, state.normalize_bitstring_modifiers)

{spec, state} =
bitstring_spec_to_algebra(spec, state, state.normalize_bitstring_modifiers, :"::")

spec = wrap_in_parens_if_inspected_atom(spec)
spec = if i == last, do: bitstring_wrap_parens(spec, i, last), else: spec
@@ -1438,15 +1440,17 @@ defmodule Code.Formatter do
{bitstring_wrap_parens(doc, i, last), state}
end

defp bitstring_spec_to_algebra({op, _, [left, right]}, state, normalize_modifiers)
defp bitstring_spec_to_algebra({op, _, [left, right]}, state, normalize_modifiers, paren_op)
when op in [:-, :*] do
normalize_modifiers = normalize_modifiers && op != :*
{left, state} = bitstring_spec_to_algebra(left, state, normalize_modifiers)
{left, state} = bitstring_spec_to_algebra(left, state, normalize_modifiers, op)
{right, state} = bitstring_spec_element_to_algebra(right, state, normalize_modifiers)
{concat(concat(left, Atom.to_string(op)), right), state}
doc = concat(concat(left, Atom.to_string(op)), right)
doc = if paren_op == :*, do: wrap_in_parens(doc), else: doc
{doc, state}
end

defp bitstring_spec_to_algebra(spec, state, normalize_modifiers) do
defp bitstring_spec_to_algebra(spec, state, normalize_modifiers, _paren_op) do
bitstring_spec_element_to_algebra(spec, state, normalize_modifiers)
end

Loading