How to fix type violation warning from a macro in Elixir 1.18

I have a macro that is used for parsing:

  defmacro left <~> right do
    quote do
      case unquote(left) do
        :error ->
          unquote(right)

        {:error, _} ->
          unquote(right)

        {:ok, _} = r ->
          r

        {:ok, _, _} = r ->
          r
      end
    end
  end

It is finding first thing that evaluates to {:ok, _} or {:ok, _, _} in a chain like parse1(args) <~> parse2(args) <~> parse3(args). We are using a macro because it is lazy. E.g. we only evaluate parse2(args) when parse1(args) failed.

In Elixir 1.18, I started getting warnings like this:

    warning: the following clause will never match:

        {:error, _}

    because it attempts to match on the result of:

        parse(args)

    which has type:

        dynamic(:error or {:ok, term()})

which is correct. This particular parser return only :error or {:ok, term()}, but other usages of this macro use othe paths including {error, _} and {:ok, _, _}.

So, the warning is technically correct, but doesn’t play well with the macro. How could I solve that issue?

1 Like

Until there’s manual type notations you’d need to work around that, like discussed e.g. in

1 Like

Hello,

In this case you could normalize the return types so errors are always a tuple.

3 Likes