【问题标题】:Dialyzer warns about no_exit on bad record construction - is this a bug?Dialyzer 警告 no_exit 构建不良记录 - 这是一个错误吗?
【发布时间】:2021-01-11 17:01:39
【问题描述】:

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

例子:

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

错误:

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()"]}}]

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

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

那么这是透析器的错误吗?

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

【问题讨论】:

    标签: erlang dialyzer


    【解决方案1】:

    不,这不是错误。

    我会说这是由于 Erlang 是动态类型的并且-type 指令在运行时不使用而造成的限制。

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

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

    【讨论】:

    • 按照“success typings”的方式报错,然后继续声明类型和发现类型的union,岂不是更好用?
    • @MaxHeiber 这种方法也有一些问题:到目前为止的所有分析都是基于原始类型:是否应该将其丢弃并重新启动? dyalizer 如何知道错误是由于定义中缺少| undefined(由联合修复)还是初始化中缺少= X(联合只能隐藏其他错误)造成的?恕我直言,一旦你有错误,任何进一步走这条路的事情都要小心翼翼,所以我认为实施这种联合是不值得的
    猜你喜欢
    • 2017-11-28
    • 2011-08-10
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    相关资源
    最近更新 更多