2

假设我有一个函数,foo/1其规范是-spec foo(atom()) -> #r{}.,其中#r{}定义为的记录在哪里-record(r, {a :: 1..789}).,但是,我foo(a) -> 800.在我的代码中有,当我对它运行透析器时,它没有警告我,(800不是“有效”返回功能的价值foo/1),我可以让透析器警告我吗?

编辑

向你学习一些 Erlang说:

Dialyzer 保留将此范围扩大到更大范围的权利。

但我找不到如何禁用它。

4

1 回答 1

0

从 Erlang 18 开始,整数范围的处理由erl_types:t_from_range/2. 正如你所看到的,为了获得一个“安全”的范围过度近似,发生了很多概括。

如果您尝试?USE_UNSAFE_RANGES(查看代码),很可能会捕获您的特定错误,但代价是可怕的:递归整数函数的本机编译和透析永远不会完成!

原因是递归函数的类型分析使用简单的固定点方法,其中初始类型接受基本情况,并使用递归情况重复扩展以包含更多值。如果要终止该过程,则在某些时候必须发生过度近似。这是一个具体的例子:

fact(1) -> 1;
fact(N) -> N * fact(N - 1).

最初fact/1假定有 type fun(none()) -> none()。使用它来分析代码,第二个子句“失败”,只有第一个子句可以。因此,在第一次迭代之后,新类型是fun(1) -> 1. 使用新类型,第二个子句可以成功,将类型扩展为fun(1|2) -> 1|2. 然后fun(1|2|3) -> 1|2|6继续进行,直到?SET_LIMIT达到 ,在这种情况下t_from_range停止使用单个值并且类型变为fun(1..255) -> pos_integer()。下一次迭代扩展1..255pos_integer()然后fun(pos_integer()) -> pos_integer()是一个固定点!

不正确的答案如下(解释下面的第一条评论):

如果您使用该-Woverspecs选项,您应该会收到此代码的警告。默认情况下不启用此选项,因为 Dialyzer 的运行假设是“可以”过度逼近函数的返回值。但是,在您的特定情况下,您实际上需要任何额外的值来产生警告。

于 2015-06-09T20:04:44.547 回答