mask_error/2 causes pattern match type errors due to extraneous patterns
Opened this issue · 0 comments
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.