Set-theoretic types and compile-time types

Hi :wave:,

I upgraded to Elixir 1.18.0, and started getting type-checking warnings in the following module:

defmodule TestModule do
  @env Mix.env()

  def prod?() do
   @env == :prod
  end 
end

Because the types don’t match:

dynamic(:dev) == :prod

What’s a recommended way to tackle this scenario with the new set-theoretic types system in Elixir?

In this particular case I would probably do it like this:

defmodule TestModule do
  if Mix.env() == :prod do
    def prod?(), do: true
  else
    def prod?(), do: false
  end
end
5 Likes

There still seems to be a problem when this function is being used with “boolean” operators, for example:

defmodule Types do
  def prod?, do: unquote(Mix.env() == :prod)

  def a_or_b do
    if Types.prod?() and :rand.uniform() > 0.5 do
      :a
    else
      :b
    end
  end
end

warns

    warning: the following conditional expression will always evaluate to dynamic(false):

        Types.prod?()

    typing violation found at:
    │
  9 │     if Types.prod?() and :rand.uniform() > 0.5 do
    │     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    │
    └─ lib/types.ex:9: Types.a_or_b/0

Rewriting the caller like this seems to work but …

  def a_or_b do
    if Types.prod?() do
      if :rand.uniform() > 0.5 do
        :a
      end
    end || :b
  end

We will fix this on Elixir v1.18.1 We will make it so it only warns when comparing across different types.

8 Likes

@josevalim was this fix implemented?
Looks like there is still an issue with compile env in 1.18.1 (see screenshot below)

We use it more like this in our app to decide whether to start certain children in the supervision tree:

The fix right now only works when comparing constants. Because you encapsulate it in a function, it no longer works, but it would work if you did @env == :dev.