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相同
  • 对于1,它将继续使用成功类型,否则将继续使用成功类型和等级库类型之间的交集

    您的情况是3,这通常不会被警告,因为您作为程序员更清楚(就透析器而言,可能
    rand:uniform(2)
    只能返回
    1
    )。您可以使用

    {透析器,[{警告,[不足,过度]}。
    

    rebar.config
    文件中,透析器自身的分析(目前)基于几种过度近似,因此无法区分您的严格规范是由于您肯定错误还是由于透析器在某个地方过度近似

    因此,它选择信任您的规范,并在以后根据该信息报告最终错误


    一般来说,由于这个原因,其他现代系统提供的与类型错误相关的信息带有“报告的所有部件,没有明确指定的责任”。在这里,事实上推理、规范和模式是不兼容的,但透析器只怪模式。这是使用它时要记住的一个怪癖。

    谢谢!我的部分问题是为什么透析器信任我。这不仅仅是因为它没有发出警告,而是因为它实际上合并了规范中的信息。这似乎不是针对欠规范的情况,而只是针对过规范的情况。这与我的预期相反:欠规范是安全的,但过度规范不是。@MaxHeiber在这两种情况下,它都通过使用类型交叉作为函数类型来合并规范中的提示,只是碰巧类型交叉是更严格的类型,在3中是规范,在2中是成功类型。这里的关键是,
    rand:uniform(2)
    完全有可能只返回
    1
    ,尽管它的规范是
    pos\u integer()
    ,所以3是一种相当常见的情况。