I have the following code:
@spec test_pass(String.t) :: (:failed | {:ok, map()})
def test_pass(pass) do
db_user = %{password_hash: @hash_for_foo}
with {:ok, ^db_user} <- Comeonin.Argon2.check_pass(db_user, pass) do
{:ok, db_user}
else
_ -> :failed
end
end
And Dyalizer is giving me the "can never match error":
⟨my_file⟩.ex:25: The pattern {'ok', _} can never match the type {'error',<<_:64,_:_*8>>}
My Question is, why? I know it can't match, and I actually don't care, that's why I'm using with
in the first place. All of the non-matching cases are handled in the else
.
How can I change my code that dialyzer
will be satisfied?
I'm not looking for @dialyzer {:nowarn_function, …}
. I already tried it with a {:error, _} -> …
expression in the else
body but no avail.
Erlang/Elixir version (elixir -v
):
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false]
Elixir 1.6.1 (compiled with OTP 19)
Argon.check_pass/2
is external, from Comeonein
.
I checked comeonin
out, and ran mix dialixier
on it and it reported several no local return
errors.
Dialyzer is very user unfriendly. Nevertheless, if it reports an error it means that based on the various type specification you have annotated your functions with, accordingly it is seeing a contradiction with your actual usage.
When Dialyzer is complaining about {'error',<<_:64,_:_*8>>}
, it means that Argon2.check_pass
has some contradictory type specifications to it, either itself, or either potentially something deeper down. Dialyzer is not very friendly in its ability to point you out exactly where and why contradictions are happening.
As I do not have full access to your code, in order to resolve the issue, at most I can point you out to following a few steps:
If Argon2.check_pass
has an explicit @spec
annotation, then comment that out and see if Dialyzer still complains.
If the complaint is gone, then modify various parts of @spec
annotation with any
until the problem is gone for identification purposes. Accordingly the issue will resolve there or either you need to dig deeper in other functions that Argon2.check_pass
relies on that may be the cause of the issue.
In the case that 1. fails, then copy paste the function defined Argon2.check_pass
as a private function: tmp_check_pass
and see how that changes the issue.
4.If need be, you may need to introduce more of these tmp_...
functions that Argon2.check_pass
is relying on in order to isolate the root cause of the complaint. Before doing that, first try commenting out all the @spec
annotations of any of the supporting functions that Argon2.check_pass
leverages and apply point 1 accordingly.
Eventually, you will arrive at a particular point in your code, where according to the specifications that you have provided to Dialyzer, that some usage of your code violates it being: of type {'error',<<_:64,_:_*8>>}
The key thought here is to try to isolate the root cause of the complaint, which Dialyzer regretfully is not too precise at pointing out for you from time to time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With