Elixir v1.19.0-rc.2 released

1. Enhancements

Elixir

  • [Regex] Raise error message when regexes are used as default values in struct fields for compatibility with Erlang/OTP 28
  • [Registry] Add key-based partitioning of duplicate registries

2. Bug fixes

Elixir

  • [Kernel] Address issue with type checking not completing on protocol consolidation

ExUnit

  • [ExUnit] Do not crash on empty test unit groups

Mix

  • [mix help] Add mix help app:APP
  • [mix test] Fix module preloading in mix test --slowest-modules=N
21 Likes

Alright folks, in a nutshell, this release addresses all feedback from the previous RCs:

  1. Fully compatible with Erlang/OTP 28.1+

  2. Struct update syntax has been adapted into a type assertion operator

  3. Addresses issues with projecting taking too long to compile

This should be our final stop before v1.19, please give it a try!

32 Likes

Looking good!

1 Like

While compiling the following functions Iโ€™m getting a warning that did not show in Elixir 1.18.x.

@impl Event
def to_payload(%GameTransactionCompleted{} = e) do
  # ...
end

def to_payload(%GameTransactionCompleted.ExternalTransaction{} = e) do
  # ...
end

def to_payload(%GameTransactionCompleted.InternalTransaction{} = e) do
  # ...
end

def to_payload(%GameTransactionCompleted.Stake{} = s) do
  # ...
end

def to_payload(%Game{} = g) do
  # ...
end

The Event protocol defines the callback as:

@spec to_payload(struct()) :: map()
def to_payload(struct)

And this is the warning that I get:

Compiling 1 file (.ex)
     warning: the 1st pattern in clause will never match:

         %Dragonara.Outbox.GameTransactionCompleted.ExternalTransaction{} = e

     because it is expected to receive type:

         dynamic(%Dragonara.Outbox.GameTransactionCompleted{})

     typing violation found at:
     โ”‚
 101 โ”‚     def to_payload(%GameTransactionCompleted.ExternalTransaction{} = e) do
     โ”‚                                                                    ~
     โ”‚
     โ””โ”€ lib/dragonara/outbox/game_transaction_completed.ex:101:68: Dragonara.Outbox.Event.Dragonara.Outbox.GameTransactionCompleted.to_payload/1

     warning: the 1st pattern in clause will never match:

         %Dragonara.Outbox.GameTransactionCompleted.InternalTransaction{} = e

     because it is expected to receive type:

         dynamic(%Dragonara.Outbox.GameTransactionCompleted{})

     typing violation found at:
     โ”‚
 120 โ”‚     def to_payload(%GameTransactionCompleted.InternalTransaction{} = e) do
     โ”‚                                                                    ~
     โ”‚
     โ””โ”€ lib/dragonara/outbox/game_transaction_completed.ex:120:68: Dragonara.Outbox.Event.Dragonara.Outbox.GameTransactionCompleted.to_payload/1

     warning: the 1st pattern in clause will never match:

         %Dragonara.Outbox.GameTransactionCompleted.Stake{} = s

     because it is expected to receive type:

         dynamic(%Dragonara.Outbox.GameTransactionCompleted{})

     typing violation found at:
     โ”‚
 140 โ”‚     def to_payload(%GameTransactionCompleted.Stake{} = s) do
     โ”‚                                                      ~
     โ”‚
     โ””โ”€ lib/dragonara/outbox/game_transaction_completed.ex:140:54: Dragonara.Outbox.Event.Dragonara.Outbox.GameTransactionCompleted.to_payload/1

     warning: the 1st pattern in clause will never match:

         %Bluelabs.Game{} = g

     because it is expected to receive type:

         dynamic(%Dragonara.Outbox.GameTransactionCompleted{})

     typing violation found at:
     โ”‚
 144 โ”‚     def to_payload(%Game{} = g) do
     โ”‚                            ~
     โ”‚
     โ””โ”€ lib/dragonara/outbox/game_transaction_completed.ex:144:28: Dragonara.Outbox.Event.Dragonara.Outbox.GameTransactionCompleted.to_payload/1

     warning: the 1st pattern in clause will never match:

         nil

     because it is expected to receive type:

         dynamic(%Dragonara.Outbox.GameTransactionCompleted{})

     typing violation found at:
     โ”‚
 171 โ”‚     def to_payload(nil) do
     โ”‚     ~~~~~~~~~~~~~~~~~~~~~~
     โ”‚
     โ””โ”€ lib/dragonara/outbox/game_transaction_completed.ex:171: Dragonara.Outbox.Event.Dragonara.Outbox.GameTransactionCompleted.to_payload/1

Generated dragonara app

Looks like the compiler is not able to understand that this is a multiclause function that acts differently depending on the struct that it receives. It is true that from the outside this function is only called with the %GameTransactionCompleted{} struct but that call also uses the other clauses for nested structs.

EDIT: I also want to note that if I rename the problematic clauses so they are not part of the same function (for example payload instead of to_payload) the warnings go away. While this workaround fixes the issue I still wonder if this should happen and why the compiler is not able to detect that the other clauses are also being called with the proper structs.