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
,透析器也不会警告您。