我有以下代码:
@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
和Dyalizer为我提供了"永远无法匹配的错误":
⟨my_file⟩.ex:25: The pattern {'ok', _} can never match the type {'error',<<_:64,_:_*8>>}
我的问题是,为什么?我知道它无法匹配,我实际上不在乎,这就是为什么我首先使用with
的原因。所有非匹配案例均在else
中处理。
如何更改dialyzer
的代码?
我不是寻找@dialyzer {:nowarn_function, …}
。我已经在else
主体中使用{:error, _} -> …
表达式进行了尝试,但无济于事。
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
是外部的,来自 Comeonein
。
我检查了comeonin
,并在其上运行mix dialixier
,并报告了几个no local return
错误。
dialyzer非常不友好。但是,如果它报告了错误,则意味着基于您已经注释函数的各种类型规范,因此,它与您的实际用法矛盾。
当透明师抱怨{'error',<<_:64,_:_*8>>}
时,这意味着Argon2.check_pass
对其本身具有一些矛盾的类型规格,或者可能会更深入。透利的能力不是很友好,可以准确地指出矛盾的地方以及为什么会发生矛盾。
由于我无法完全访问您的代码,以解决问题,最多可以指出您遵循几个步骤:
-
如果
Argon2.check_pass
具有明确的@spec
注释,请评论一下,看看Dialyzer是否仍然抱怨。 -
如果投诉消失了,请用
any
修改@spec
注释的各个部分,直到出于识别目的而解决该问题。因此,该问题将在此解决,或者您需要在Argon2.check_pass
所依赖的其他功能中进行更深入的研究可能是问题的原因。 -
如果1.失败,则将定义
Argon2.check_pass
的函数复制为私人函数:tmp_check_pass
,看看如何改变问题。
4.如果需要,您可能需要介绍更多Argon2.check_pass
依赖的tmp_...
功能以隔离投诉的根本原因。在此之前,首先尝试评论Argon2.check_pass
的任何支持功能的所有@spec
注释,并相应地应用点1。
最终,您将到达代码中的特定点,根据您提供给Dialyzer的规格,某些使用代码违反了IT:类型{'error',<<_:64,_:_*8>>}
这里的关键想法是试图隔离投诉的根本原因,而透视遗憾的是,这并不是在不时为您指出的问题。
作为另一个问题:dialyzer通常永远是错误的&quot&quot',但我不知道我的@spec是如何不正确的,透明师检测到您的Comeonin.Argon2.check_pass()
呼叫永远不会返回确定,所以。..
我还没有解决方案,只想澄清原因。