Skip to content

mask_error/2 causes pattern match type errors due to extraneous patterns #16

@heydtn

Description

@heydtn

Love the library, thanks for putting this out!

Describe the bug
When using mask_error/2, dialyzer will throw type errors for conditions which are handled by mask_error/2 but are extraneous based on the typing of the input value.

To Reproduce

case :random.uniform(3) do
  3 -> :ok
  2 -> {:ok, true}
  _ -> {:error, :test}
end
|> mask_error(:testing)

case :random.uniform(2) do
  2 -> :ok
  _ -> {:ok, true}
end
|> mask_error(:testing)

case :random.uniform(2) do
  2 -> :ok
  _ -> {:error, :test}
end
|> mask_error(:testing)

Running dialyzer will report the second and third calls to mask_error/2 as having a pattern_match error, as dialyzer determines that the second case statement will never produce {:error, _}, and the third case statement will never produce :ok.

________________________________________________________________________________
/example.ex:12:pattern_match
The pattern can never match the type.

Pattern:
{:error, _}

Type:
:ok | {:ok, true}

________________________________________________________________________________
/example.ex:18:pattern_match
The pattern can never match the type.

Pattern:
{:ok, 95}

Type:
:ok

Expected behavior
The typing of the input Result should not cause mask_error/2 to be flagged with pattern_match errors, as long as the input type is covered within Brex.Result.Base.t().

Additional context
I'm guessing this is because of how it's implemented as a macro. A similar implementation as a normal method does not throw a type error:

  @spec masq_error(Brex.Result.Base.t(a), b) :: 
          :ok | {:ok, a} | {:error, b} 
        when a: var, b: var
  def masq_error(a, b) do
    case a do
      :ok -> :ok
      {:ok, _} = v -> v
      {:error, _} -> {:error, b}
    end
  end

Most of the time, once I begin piping results around, they get normalized to {:ok, value} and {:error, value}, which means that mask_error/2 begins throwing these type errors all over the place =(. I haven't tested, but this same issue might also occur when using convert_error/3.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions