Dialyzer 在不良记录构建时警告 no_exit - 这是一个错误吗?

Max*_*ber 5 erlang dialyzer

当 Dialyzer 遇到未初始化所需字段的记录文字时,它认为控制流在记录文字所在的行处停止。

例子:

-module(sample).
-export([foo/0]).
-record(boo, {a :: number()}).
foo() ->
    erlang:display(#boo{}).
Run Code Online (Sandbox Code Playgroud)

错误:

13> dialyzer:run([{files, ["/Users/mheiber/sample.erl"]}, {from, src_code}]).
[{warn_return_no_exit,
     {"/Users/mheiber/sample.erl",11},
     {no_return,[only_normal,foo,0]}},
 {warn_matching,
     {"/Users/mheiber/sample.erl",12},
     {record_constr,
         ["#boo{a::'undefined'}","a::number()"]}}]
Run Code Online (Sandbox Code Playgroud)

这是一个错误吗?Erlang 的运行时语义与 Dialyzer 对它们建模的方式匹配:ERTS(无论好坏!)不断前进,愉快地将原子“未定义”分配给任何未定义的字段。

澄清:我在这里的意思是,在可行的情况下,最好让静态检查反映 Erlang 在运行时的工作方式。

那么这是一个透析器错误吗?

Dialyzer 处理这些不正确初始化的记录的方式是有害的,因为它会触发一连串虚假警告——当 Dialyzer 认为某行函数foo无法访问时,任何只能从 from 访问的函数foo也被认为是死的。

Jos*_*é M 5

不,这不是错误。

我会说这是一个限制,因为 Erlang 是动态类型的,并且 -type指令不在运行时使用。

透析器建立在 ERTS 之上,而不是相反。

这种情况下的问题是dialyzer不知道如何继续执行:它应该使用记录定义中定义的类型还是实际的记录初始化?它报告一个错误,实际的修复留给程序员。

  • @MaxHeiber 这种方法也有一些问题:到目前为止的所有分析都是基于原始类型:是否应该将其丢弃并重新启动?dyalizer 如何知道错误是否是由于缺少 `| 造成的?定义中未定义的(将由联合修复)或初始化中缺少的“= X”(联合只能隐藏其他错误)?恕我直言,一旦你犯了错误,任何进一步的事情都应该持保留态度,所以我认为实施这种联合是不值得的 (2认同)