我有以下代码:
@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
端
Dyalizer正在给我“永远不能匹配的错误”:
⟨my_file⟩.ex:25: The pattern {'ok', _} can never match the type {'error',<<_:64,_:_*8>>}
我的问题是,为什么?我知道它无法匹配,我实际上并不在意,这就是我首先使用with
的原因。所有不匹配的案例都在else
。
如何更改dialyzer
会满足的代码?
我不正在寻找@dialyzer {:nowarn_function, …}
。我已经在{:error, _} -> …
机构中使用else
表达式尝试了它,但没有用。
Erlang / Elixir版本(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
我检查了comeonin
,并在其上运行了mix dialixier
,并报告了多个no local return
错误。
答案 0 :(得分:4)
Dialyzer非常不友好。然而,如果它报告错误,则意味着基于各种类型规范,您已经注释了您的功能,因此它看起来与您的实际使用相矛盾。
当Dialyzer抱怨{'error',<<_:64,_:_*8>>}
时,这意味着Argon2.check_pass
对它有一些相互矛盾的类型规范,要么本身,要么可能是更深层次的东西。 Dialyzer不能非常友好地指出你究竟发生矛盾的地点和原因。
由于我无法完全访问您的代码,为了解决问题,我最多可以指出您执行以下几个步骤:
如果Argon2.check_pass
有明确的@spec
注释,那么请将其评论出去,看看Dialyzer是否还会抱怨。
如果投诉已经消失,请使用@spec
修改any
注释的各个部分,直到问题消失为止进行识别。因此,问题将在那里得到解决,或者您需要深入研究Argon2.check_pass
可能导致问题的其他功能。
如果1.失败,则复制粘贴定义Argon2.check_pass
的函数作为私有函数:tmp_check_pass
,看看它是如何改变问题的。
4.如果需要,您可能需要引入更多tmp_...
Argon2.check_pass
所依赖的@spec
函数,以便找出投诉的根本原因。在此之前,首先尝试评论Argon2.check_pass
利用的任何支持函数的所有{'error',<<_:64,_:_*8>>}
注释,并相应地应用第1点。
最终,您将到达代码中的特定位置,根据您向Dialyzer提供的规范,您的代码的某些用法违反了以下类型:{{1}}类型
这里的关键思考是试图找出投诉的根本原因,而Dialyzer遗憾地指出不时太精确了。
答案 1 :(得分:0)
正如另一个问题"Dialyzer is usually never wrong", but I can't figure out how my @spec is incorrect所说,Dialyzer检测到您的Comeonin.Argon2.check_pass()
呼叫将永远不会返回OK,所以...
我还没有解决方案,只是想弄清楚原因。