Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
heydtn opened this issue Feb 13, 2020 · 0 comments
Open

Comments

@heydtn
Copy link

heydtn commented Feb 13, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant