Dialyzer不会发出此函数返回类型不一致的信号
-spec myfun(integer()) -> zero | one.
myfun(0) -> zero;
myfun(1) -> one;
myfun(2) -> other_number.
但它检测到最后一行是
的情况myfun(_) -> other_number.
为什么会这样? 上面应该是一个非常简单的案例,我相信......
由于
答案 0 :(得分:4)
对于“为什么透析器没有......”这类问题的简单回答是“因为它的设计总是正确的”或“因为它永远不会承诺它会捕获所有或任何特定的东西”。
对于更复杂的答案,您需要进一步指定您的问题。如果我在模块中编写示例:
-module(bar).
-export([myfun1/1, myfun2/1]).
-spec myfun1(integer()) -> zero | one.
myfun1(0) -> zero;
myfun1(1) -> one;
myfun1(2) -> other_number.
-spec myfun2(integer()) -> zero | one.
myfun2(0) -> zero;
myfun2(1) -> one;
myfun2(_) -> other_number.
透析它:
$ dialyzer bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis... done in 0m0.64s
done (passed successfully)
......两者之间都没有“检测到”差异,导致两者都不是“错误”。事实上,代码在某种程度上更通用(可以返回额外的值),并且在某些方面更具限制性(不能处理每个整数,对于版本1)而不是规范。
可以使用-Woverspecs
找到第二个版本的问题:
$ dialyzer -Woverspecs bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis...
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero'
done in 0m0.58s
done (warnings were emitted)
警告准确地解释了规范比代码更具限制性。
极不寻常的-Wspecdiffs
:
$ dialyzer -Wspecdiffs bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis...
bar.erl:5: Type specification bar:myfun1(integer()) -> 'zero' | 'one' is not equal to the success typing: bar:myfun1(0 | 1 | 2) -> 'one' | 'other_number' | 'zero'
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero'
done in 0m0.61s
done (warnings were emitted)
鼓励-Woverspecs
和-Wspecdiffs
操作模式,因为透析器的类型分析可以并且将概括类型,因此“以更严格的方式指定的东西”可以是泛化的结果。 / p>
也可能是你打算只用0和1作为参数调用这些函数,在这种情况下规范是'ok'。