如何在匹配所有 else 的 `with` 语句中避免 Dialyzer 出现“永远无法匹配”错误?
How to avoid a “can never match” error from Dialyzer in a `with` statement that has a match all `else`?
我有以下代码:
@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
is external, from Comeonein
.
我检查了 comeonin
,运行 mix dialixier
并报告了几个 no local return
错误。
Dialyzer 对用户非常不友好。然而,如果它报告错误,则意味着根据您对函数进行注释的各种类型规范,因此它发现与您的实际用法相矛盾。
当 Dialyzer 抱怨 {'error',<<_:64,_:_*8>>}
时,这意味着 Argon2.check_pass
有一些相互矛盾的类型规范,要么是它本身,要么是潜在的更深层次的东西。 Dialyzer 在准确指出矛盾发生的位置和原因方面不是很友好。
由于我没有完全访问你的代码的权限,为了解决这个问题,我最多可以指出你遵循以下几个步骤:
如果 Argon2.check_pass
有明确的 @spec
注释,然后将其注释掉并查看 Dialyzer 是否仍然抱怨。
如果投诉没有了,那么用any
修改@spec
注释的各个部分,直到问题消失,以供识别。因此,该问题将在那里解决,或者您需要深入研究 Argon2.check_pass
所依赖的其他功能,这可能是问题的原因。
如果 1. 失败,则复制粘贴定义为 Argon2.check_pass
的函数作为私有函数:tmp_check_pass
看看如何改变问题。
4.If 需要,您可能需要引入更多 Argon2.check_pass
所依赖的 tmp_...
函数,以便找出投诉的根本原因。在此之前,首先尝试注释掉 Argon2.check_pass
所利用的任何支持函数的所有 @spec
注释,并相应地应用第 1 点。
最终,您将到达代码中的一个特定点,根据您提供给 Dialyzer 的规范,您的代码的某些用法违反了它:类型 {'error',<<_:64,_:_*8>>}
这里的关键思想是试图找出投诉的根本原因,遗憾的是 Dialyzer 不时为您指出的问题不是太精确。
正如另一个问题 所说,Dialyzer 检测到您的 Comeonin.Argon2.check_pass()
呼叫永远不会 return 好的,所以 ...
目前还没有解决办法,想弄清楚原因。
我有以下代码:
@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
is external, from Comeonein
.
我检查了 comeonin
,运行 mix dialixier
并报告了几个 no local return
错误。
Dialyzer 对用户非常不友好。然而,如果它报告错误,则意味着根据您对函数进行注释的各种类型规范,因此它发现与您的实际用法相矛盾。
当 Dialyzer 抱怨 {'error',<<_:64,_:_*8>>}
时,这意味着 Argon2.check_pass
有一些相互矛盾的类型规范,要么是它本身,要么是潜在的更深层次的东西。 Dialyzer 在准确指出矛盾发生的位置和原因方面不是很友好。
由于我没有完全访问你的代码的权限,为了解决这个问题,我最多可以指出你遵循以下几个步骤:
如果
Argon2.check_pass
有明确的@spec
注释,然后将其注释掉并查看 Dialyzer 是否仍然抱怨。如果投诉没有了,那么用
any
修改@spec
注释的各个部分,直到问题消失,以供识别。因此,该问题将在那里解决,或者您需要深入研究Argon2.check_pass
所依赖的其他功能,这可能是问题的原因。如果 1. 失败,则复制粘贴定义为
Argon2.check_pass
的函数作为私有函数:tmp_check_pass
看看如何改变问题。
4.If 需要,您可能需要引入更多 Argon2.check_pass
所依赖的 tmp_...
函数,以便找出投诉的根本原因。在此之前,首先尝试注释掉 Argon2.check_pass
所利用的任何支持函数的所有 @spec
注释,并相应地应用第 1 点。
最终,您将到达代码中的一个特定点,根据您提供给 Dialyzer 的规范,您的代码的某些用法违反了它:类型 {'error',<<_:64,_:_*8>>}
这里的关键思想是试图找出投诉的根本原因,遗憾的是 Dialyzer 不时为您指出的问题不是太精确。
正如另一个问题 Comeonin.Argon2.check_pass()
呼叫永远不会 return 好的,所以 ...
目前还没有解决办法,想弄清楚原因。