Erlang 为什么透析器相信有太特殊返回类型的规格?
我希望添加规范不会降低安全性,但这正是以下情况下发生的情况 在下面的代码中,透析器(错误地)相信我返回的条形码类型是Erlang 为什么透析器相信有太特殊返回类型的规格?,erlang,dialyzer,Erlang,Dialyzer,我希望添加规范不会降低安全性,但这正是以下情况下发生的情况 在下面的代码中,透析器(错误地)相信我返回的条形码类型是1。这导致它说foo()中的模式永远不会匹配——错误的建议,如果注意,将导致运行时错误 -模块(示例)。 -导出([foo/0])。 foo()-> 的case bar() 1->ok; 2->什么 结束。 -等级库栏()->1。 条()-> 兰德:统一(2)。 删除bar/0的规格可以解决问题–但为什么透析器信任我? 透析器违反了它的“无假阳性”承诺:当没有错误时它会发出警告。
1
。这导致它说foo()中的模式永远不会匹配——错误的建议,如果注意,将导致运行时错误
-模块(示例)。
-导出([foo/0])。
foo()->
的case bar()
1->ok;
2->什么
结束。
-等级库栏()->1。
条()->
兰德:统一(2)。
删除bar/0
的规格可以解决问题–但为什么透析器信任我?
透析器违反了它的“无假阳性”承诺:当没有错误时它会发出警告。而且(更糟糕的是)透析器轻推引入一个新的错误。透析器在检查每个功能的规格之前,计算每个功能的成功类型,此操作有几个可能的结果:
-Wunderspecs
或-Wspecdiffs
发出警告-Woverspecs
或-Wspecdiffs
发出警告-1..1
和pos\u integer()
):与2相同rand:uniform(2)
只能返回1
)。您可以使用
{透析器,[{警告,[不足,过度]}。
在
rebar.config
文件中,透析器自身的分析(目前)基于几种过度近似,因此无法区分您的严格规范是由于您肯定错误还是由于透析器在某个地方过度近似
因此,它选择信任您的规范,并在以后根据该信息报告最终错误
一般来说,由于这个原因,其他现代系统提供的与类型错误相关的信息带有“报告的所有部件,没有明确指定的责任”。在这里,事实上推理、规范和模式是不兼容的,但透析器只怪模式。这是使用它时要记住的一个怪癖。谢谢!我的部分问题是为什么透析器信任我。这不仅仅是因为它没有发出警告,而是因为它实际上合并了规范中的信息。这似乎不是针对欠规范的情况,而只是针对过规范的情况。这与我的预期相反:欠规范是安全的,但过度规范不是。@MaxHeiber在这两种情况下,它都通过使用类型交叉作为函数类型来合并规范中的提示,只是碰巧类型交叉是更严格的类型,在3中是规范,在2中是成功类型。这里的关键是,
rand:uniform(2)
完全有可能只返回1
,尽管它的规范是pos\u integer()
,所以3是一种相当常见的情况。