Skip to content

Commit

Permalink
Merge branch 'elixir-lang:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasvegi authored Sep 22, 2023
2 parents 37be217 + 1ecdd2d commit 886c157
Show file tree
Hide file tree
Showing 14 changed files with 362 additions and 103 deletions.
79 changes: 79 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,97 @@
# Changelog for Elixir v1.16

## Code snippets in diagnostics

Elixir v1.15 introduced a new compiler diagnostic format and the ability to print multiple error diagnostics per compilation (in addition to multiple warnings).

With Elixir v1.16, we also include code snippets in exceptions and diagnostics raised by the compiler. For example, a syntax error now includes a pointer to where the error happened:

```
** (SyntaxError) invalid syntax found on nofile:1:17:
error: syntax error before: '*'
1 │ [1, 2, 3, 4, 5, *]
│ ^
└─ lib/my_app.ex:1:17
```

For mismatched delimiters, it now shows both delimiters:

```
** (MismatchedDelimiterError) mismatched delimiter found on nofile:1:18:
error: unexpected token: )
1 │ [1, 2, 3, 4, 5, 6)
│ │ └ mismatched closing delimiter (expected "]")
│ └ unclosed delimiter
└─ lib/my_app.ex:1:18
```

Errors and warnings diagnostics also include code snippets. When possible, we will show precise spans, such as on undefined variables:

```
error: undefined variable "unknown_var"
5 │ a - unknown_var
│ ^^^^^^^^^^^
└─ lib/sample.ex:5:9: Sample.foo/1
```

Otherwise the whole line is underlined:

```
error: function names should start with lowercase characters or underscore, invalid name CamelCase
3 │ def CamelCase do
│ ^^^^^^^^^^^^^^^^
└─ lib/sample.ex:3
```

## Revamped documentation

TODO: Guides, diagrams, anti-patterns, cheatsheets.

## v1.16.0-dev

### 1. Enhancements

#### EEx

* [EEx] Include relative file information in diagnostics

#### Elixir

* [Code] Automatically include columns in parsing options
* [Code] Introduce `MismatchedDelimiterError` for handling mismatched delimiter exceptions
* [Code.Fragment] Handle anonymous calls in fragments
* [Kernel] Suggest module names based on suffix and casing errors when the module does not exist in `UndefinedFunctionError`
* [Kernel.ParallelCompiler] Introduce `Kernel.ParallelCompiler.pmap/2` to compile multiple additional entries in parallel
* [Macro] Add `Macro.compile_apply/4`
* [String] Update to Unicode 15.1.0

### 2. Bug fixes

#### Elixir

* [IO] Raise when using `IO.binwrite/2` on terminated device (mirroring `IO.write/2`)
* [Kernel] Do not expand aliases recursively (the alias stored in Macro.Env is already expanded)
* [Kernel] Ensure `dbg` module is a compile-time dependency
* [Kernel] Warn when a private function or macro uses `unquote/1` and the function/macro itself is unused
* [Path] Ensure `Path.relative_to/2` returns a relative path when the given argument does not share a common prefix with `cwd`

#### ExUnit

* [ExUnit] Raise on incorrectly dedented doctests

### 3. Soft deprecations (no warnings emitted)

#### Elixir

* [Kernel.ParallelCompiler] Deprecate `Kernel.ParallelCompiler.async/1` in favor of `Kernel.ParallelCompiler.pmap/2`
* [Path] Deprecate `Path.safe_relative_to/2` in favor of `Path.safe_relative/2`

### 4. Hard deprecations
Expand Down
38 changes: 20 additions & 18 deletions lib/elixir/lib/enum.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2390,7 +2390,14 @@ defmodule Enum do
def random(enumerable) when is_list(enumerable) do
case length(enumerable) do
0 -> raise Enum.EmptyError
length -> enumerable |> drop_list(random_integer(0, length - 1)) |> hd()
length -> enumerable |> drop_list(random_count(length)) |> hd()
end
end

def random(first.._//step = range) do
case Range.size(range) do
0 -> raise Enum.EmptyError
size -> first + random_count(size) * step
end
end

Expand All @@ -2401,14 +2408,14 @@ defmodule Enum do
[]

{:ok, count, fun} when is_function(fun, 1) ->
slice_list(fun.(enumerable), random_integer(0, count - 1), 1, 1)
slice_list(fun.(enumerable), random_count(count), 1, 1)

# TODO: Deprecate me in Elixir v1.18.
{:ok, count, fun} when is_function(fun, 2) ->
fun.(random_integer(0, count - 1), 1)
fun.(random_count(count), 1)

{:ok, count, fun} when is_function(fun, 3) ->
fun.(random_integer(0, count - 1), 1, 1)
fun.(random_count(count), 1, 1)

{:error, _} ->
take_random(enumerable, 1)
Expand All @@ -2420,6 +2427,10 @@ defmodule Enum do
end
end

defp random_count(count) do
:rand.uniform(count) - 1
end

@doc """
Invokes `fun` for each element in the `enumerable` with the
accumulator.
Expand Down Expand Up @@ -3609,7 +3620,7 @@ defmodule Enum do
sample = Tuple.duplicate(nil, count)

reducer = fn elem, {idx, sample} ->
jdx = random_integer(0, idx)
jdx = random_index(idx)

cond do
idx < count ->
Expand All @@ -3630,7 +3641,7 @@ defmodule Enum do

def take_random(enumerable, count) when is_integer(count) and count >= 0 do
reducer = fn elem, {idx, sample} ->
jdx = random_integer(0, idx)
jdx = random_index(idx)

cond do
idx < count ->
Expand Down Expand Up @@ -3666,6 +3677,9 @@ defmodule Enum do

defp take_random_list_one([], current, _), do: [current]

defp random_index(0), do: 0
defp random_index(idx), do: :rand.uniform(idx + 1) - 1

@doc """
Takes the elements from the beginning of the `enumerable` while `fun` returns
a truthy value.
Expand Down Expand Up @@ -4149,18 +4163,6 @@ defmodule Enum do
end)
end

defp random_integer(limit, limit) when is_integer(limit) do
limit
end

defp random_integer(lower_limit, upper_limit) when upper_limit < lower_limit do
random_integer(upper_limit, lower_limit)
end

defp random_integer(lower_limit, upper_limit) do
lower_limit + :rand.uniform(upper_limit - lower_limit + 1) - 1
end

## Implementations

## all?/1
Expand Down
2 changes: 1 addition & 1 deletion lib/elixir/lib/string.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule String do
"hello world"
The functions in this module act according to
[The Unicode Standard, Version 15.0.0](http://www.unicode.org/versions/Unicode15.0.0/).
[The Unicode Standard, Version 15.1.0](http://www.unicode.org/versions/Unicode15.1.0/).
## Interpolation
Expand Down
7 changes: 5 additions & 2 deletions lib/elixir/lib/system.ex
Original file line number Diff line number Diff line change
Expand Up @@ -755,9 +755,12 @@ defmodule System do
Sets multiple environment variables.
Sets a new value for each environment variable corresponding
to each `{key, value}` pair in `enum`. Keys are automatically
converted to strings, values are sent as is. `nil` values erase
to each `{key, value}` pair in `enum`. Keys and non-nil values
are automatically converted to charlists. `nil` values erase
the given keys.
Overall, this is a convenience wrapper around `put_env/2` and
`delete_env/2` with support for different key and value formats.
"""
@spec put_env(Enumerable.t()) :: :ok
def put_env(enum) do
Expand Down
124 changes: 94 additions & 30 deletions lib/elixir/scripts/windows_installer/installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,18 @@ InstallDir "$PROGRAMFILES64\Elixir"

Page custom CheckOTPPageShow CheckOTPPageLeave

var Dialog
var DownloadOTPLink
var InstalledOTPRelease
var OTPPath

var Dialog
var NoOTPLabel
var NoOTPLabelCreated
var OTPMismatchLabel
var OTPMismatchLabelCreated
var DownloadOTPLink
var DownloadOTPLinkCreated
var VerifyOTPButton
var VerifyOTPButtonCreated
Function CheckOTPPageShow
!insertmacro MUI_HEADER_TEXT "Checking Erlang/OTP" ""

Expand All @@ -26,15 +34,61 @@ Function CheckOTPPageShow
Abort
${EndIf}

EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
StrCpy $OTPPath $0
Call VerifyOTP

${If} $OTPPath == ""
${NSD_CreateLabel} 0 0 100% 20u "Couldn't find existing Erlang/OTP installation. Click the link below to download and install it before proceeding."
${NSD_CreateLink} 0 25u 100% 20u "Download Erlang/OTP ${OTP_RELEASE}"
nsDialogs::Show
FunctionEnd

Function VerifyOTP
${If} $NoOTPLabelCreated == "true"
ShowWindow $NoOTPLabel ${SW_HIDE}
${EndIf}

${If} $OTPMismatchLabelCreated == "true"
ShowWindow $OTPMismatchLabel ${SW_HIDE}
${EndIf}

${If} $DownloadOTPLinkCreated == "true"
ShowWindow $DownloadOTPLink ${SW_HIDE}
${Else}
StrCpy $DownloadOTPLinkCreated "true"
${NSD_CreateLink} 0 60u 100% 20u "Download Erlang/OTP ${OTP_RELEASE}"
Pop $DownloadOTPLink
${NSD_OnClick} $DownloadOTPLink OpenOTPDownloads
ShowWindow $DownloadOTPLink ${SW_HIDE}
${EndIf}

${If} $VerifyOTPButtonCreated == "true"
ShowWindow $VerifyOTPButton ${SW_HIDE}
${Else}
StrCpy $VerifyOTPButtonCreated "true"
${NSD_CreateButton} 0 80u 25% 12u "Verify Erlang/OTP"
Pop $VerifyOTPButton
${NSD_OnClick} $VerifyOTPButton VerifyOTP
ShowWindow $VerifyOTPButton ${SW_HIDE}
${EndIf}

StrCpy $0 0
loop:
EnumRegKey $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" $0
StrCmp $1 "" done
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$1" ""
StrCpy $OTPPath $1
IntOp $0 $0 + 1
goto loop
done:

${If} $OTPPath == ""
${If} $NoOTPLabelCreated != "true"
StrCpy $NoOTPLabelCreated "true"
${NSD_CreateLabel} 0 0 100% 20u "Couldn't find existing Erlang/OTP installation. Click the link below to download and install it before proceeding."
Pop $NoOTPLabel
${EndIf}

ShowWindow $NoOTPLabel ${SW_SHOW}
ShowWindow $DownloadOTPLink ${SW_SHOW}
ShowWindow $VerifyOTPButton ${SW_SHOW}

${Else}
nsExec::ExecToStack `$OTPPath\bin\erl.exe -noinput -eval "\
io:put_chars(erlang:system_info(otp_release)),\
Expand All @@ -45,24 +99,25 @@ Function CheckOTPPageShow
${If} $0 == 0
StrCpy $InstalledOTPRelease $1
${If} $InstalledOTPRelease == ${OTP_RELEASE}
${NSD_CreateLabel} 0 0 100% 20u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath. Please proceed."
${ElseIf} $2 < ${OTP_RELEASE}
${NSD_CreateLabel} 0 0 100% 30u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir installer was precompiled for Erlang/OTP ${OTP_RELEASE}. \
We recommend checking if there is an Elixir version precompiled for Erlang/OTP $InstalledOTPRelease. Otherwise, proceed."
${NSD_CreateLabel} 0 0 100% 60u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath. Please proceed."

${Else}
SetErrorlevel 5
MessageBox MB_ICONSTOP "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir version was precompiled for Erlang/OTP ${OTP_RELEASE}. \
Please upgrade your Erlang/OTP version or choose an Elixir installer matching your Erlang/OTP version"
Quit
${If} $OTPMismatchLabelCreated != "true"
StrCpy $OTPMismatchLabelCreated "true"
${NSD_CreateLabel} 0 0 100% 60u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir installer was precompiled for Erlang/OTP ${OTP_RELEASE}. \
$\r$\n$\r$\nYou can either search for another Elixir installer precompiled for Erlang/OTP $InstalledOTPRelease or download Erlang/OTP ${OTP_RELEASE} and install before proceeding."
Pop $OTPMismatchLabel
${EndIf}

ShowWindow $OTPMismatchLabel ${SW_SHOW}
ShowWindow $DownloadOTPLink ${SW_SHOW}
ShowWindow $VerifyOTPButton ${SW_SHOW}
${EndIf}
${Else}
SetErrorlevel 5
MessageBox MB_ICONSTOP "Found existing Erlang/OTP installation at $OTPPath but checking it exited with $0: $1"
Quit
${EndIf}
${EndIf}

nsDialogs::Show
FunctionEnd

Function OpenOTPDownloads
Expand Down Expand Up @@ -93,15 +148,18 @@ Function FinishPageShow
Abort
${EndIf}

${NSD_CreateCheckbox} 0 0 195u 10u "&Add $INSTDIR\bin to %PATH%"
Pop $AddElixirToPathCheckbox
SendMessage $AddElixirToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
; we add to PATH using erlang, so there must be an OTP installed to do so.
${If} "$OTPPath" != ""
${NSD_CreateCheckbox} 0 0 195u 10u "&Add $INSTDIR\bin to %PATH%"
Pop $AddElixirToPathCheckbox
SendMessage $AddElixirToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0

${NSD_CreateCheckbox} 0 20u 195u 10u "&Add $OTPPath\bin to %PATH%"
Pop $AddOTPToPathCheckbox
SendMessage $AddOTPToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0

EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
${NSD_CreateCheckbox} 0 20u 195u 10u "&Add $0\bin to %PATH%"
Pop $AddOTPToPathCheckbox
SendMessage $AddOTPToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
${NSD_CreateLabel} 0 40u 100% 20u "Note: you need to restart your shell for the environment variable changes to take effect."
${EndIf}

nsDialogs::Show
FunctionEnd
Expand Down Expand Up @@ -145,9 +203,15 @@ var RemoveElixirFromPathCheckbox
Function un.FinishPageShow
!insertmacro MUI_HEADER_TEXT "Remove from %PATH%" ""

EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
ReadRegStr $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
StrCpy $OTPPath $0
StrCpy $0 0
loop:
EnumRegKey $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" $0
StrCmp $1 "" done
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$1" ""
StrCpy $OTPPath $1
IntOp $0 $0 + 1
goto loop
done:

nsDialogs::Create 1018
Pop $Dialog
Expand Down
Loading

0 comments on commit 886c157

Please sign in to comment.