Erlang透析器:只接受某些整数?

Erlang透析器:只接受某些整数?,erlang,dialyzer,Erlang,Dialyzer,假设我有一个函数,foo/1,它的规范是-spec foo(atom())->r{}.,其中\r{}是一个定义为-record(r,{a::1..789}的记录。,但是,我的代码中有foo(a)->800.在我的代码中,当我对它运行透析器时,它没有警告我这一点,800是无效的”函数的返回值foo/1),我能让透析器警告我吗 编辑 说: 透析器保留将此范围扩大到更大范围的权利 但是我找不到如何禁用它。从Erlang 18开始,整数范围的处理由erl\u类型完成:t\u from\u range/2

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

编辑

说:

透析器保留将此范围扩大到更大范围的权利


但是我找不到如何禁用它。

从Erlang 18开始,整数范围的处理由
erl\u类型完成:t\u from\u range/2
。正如你所能做的那样,有很多的泛化可以得到一个范围的“安全”过度近似

如果您试图
?使用\u UNSAFE\u RANGES
(请参阅代码),很可能会发现您的特定错误,但代价很高:递归整数函数的本机编译和透析将永远无法完成

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

fact(1) -> 1;
fact(N) -> N * fact(N - 1).
最初假定
fact/1
具有类型
fun(none())->none()
。用它来分析代码,第二条是“失败”,只有第一条是可以的。因此,在第一次迭代之后,新类型是
fun(1)->1
。使用新类型,第二个子句可以成功,将类型扩展为
fun(1 | 2)->1 | 2
。然后
fun(1 | 2 | 3)->1 | 2 | 6
这将继续,直到达到
?设置_限制
,在这种情况下
t_from_range
停止使用单个值,类型变为
fun(1..255)->pos u integer()
。下一次迭代将
1..255
扩展为
pos\u integer()
,然后
fun(pos\u integer())->pos\u integer()
是一个固定点

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


如果使用
-Woverspecs
选项,您应该会收到此代码的警告。默认情况下,此选项不启用,因为透析器在假设“正常”的情况下工作,以超过函数的返回值。但是,在您的特定情况下,您实际上需要任何额外的值来生成警告。

foo(a)
不会受到记录
r
的类型规范的影响,因为它只接受atom作为参数。实际上不会。如果范围很小,比如说
1..3
,您返回
4
,即使您没有指定
-Woverspecs
,透析器也会警告您,但是如果范围很大,即使您指定
-Woverspecs
,透析器也不会警告您。