2

在一个有大约 6000 行 Erlang 代码但没有类型-spec()注释的项目中,我尝试了以下方法:

typer --annotate *.erl

我用*.erl带注释的文件替换了所有文件并运行

dialyzer --src -c *.erl

我预计会收到很多警告(第一次运行透析器/打字机组合),但在完成它之后,所有透析器报告的是 user_default 中的 2 个旧调用,同时不存在函数。

没有触发其他默认警告。

我使用它时犯了错误还是这样的结果很常见?

自动注释与typerand的组合dialyzer不是很有用,还是我很幸运,我的代码没有问题?


旁注:我不得不注释掉 3 或 4 -spec()s 因为dialyzer crashed on them

我正在使用来自 Erlang R13B04 的 Dialyzer v2.2.0 和 TypEr 版本 v0.1.7.4

4

1 回答 1

3

作为在 erlang-bugs 列表中报告错误的副作用,我从透析器和打字机的发明者 Kostis Sagonas 那里得到了详细的回答。

对于我的侧面问题,我得到了以下出色而详细的答案:

2011 年 5 月 1 日星期日下午 5:53,Kostis Sagonas 写道:

佩尔斯特里辛格写道:

顺便说一句:在 typer 中执行 --annotate 然后在没有手动调整规范的情况下进行透析器时没有收到任何警告是否正常

是的。实际上,typer只是dialyzer基本类型推断的一个前端(即没有warning标识组件)。

IMO,如果您不打算手动“按摩”您获得的规格并为其中一些规格提供更多信息,那么这样做几乎没有意义。看看你以前的程序。如果您引入如下类型,则可以更好地表达两个 << :64, :_*8>> 类型指的是相同数量的事实:

  -type packet() :: <<_:64,_:_*8>>,

同样对于通道:

  -type channel() :: atom() | pid() |{atom(),_}.

然后规范看起来会更好。此外,dialyzer/typer 没有关于您打算在函数的第二个参数中使用什么类型的乐趣的信息,recv/3但您确实做到了!从代码中可以清楚地看出它需要#can_pkt{}记录,那么为什么不为其字段添加适当的类型并为其引入一个类型呢?

  -record(can_pkt, {id :: id(), data :: binary(), timestamp :: ts()}).
  -type can_pkt() :: #can_pkt{}.

那么规格看起来会更好:

  -spec recv(packet(), fun((can_pkt()) -> R), channel()) -> R.
  -spec decode(packet()) -> can_pkt().

请注意,我使用了一个占位符类型变量R来表示函数recv/2返回其第二个参数中 fun 返回的任何类型的事实。你可能知道这个类型是什么,所以你也应该为它引入一个类型并使用它的正确名称。

希望这可以帮助,

科斯蒂斯

PS。很遗憾您将其发布在 erlang-bugs 中,因为上面包含的信息在 IMO 中比实际的错误更有趣。

由于他引用了一个代码片段,我将其包含在我的错误报告中,因此我将其包含在此处。以下代码片段由 自动注释typer --annotate

-record(can_pkt, {id, data, timestamp}).

-spec recv(<<_:64,_:_*8>>,fun((_) -> 
      any()),atom() | pid() | {atom(),_}) -> any().

recv(Packet, Recv_fun, Chan) ->
    P = decode(Packet),
    #can_pkt{id=Can_id, data=Can_data}=P,
    Recv_fun(P).

-spec decode(<<_:64,_:_*8>>) -> 
      #can_pkt{id::<<_:11>>,data::binary(),timestamp::char()}.

decode(<<_:12, Len:4, Timestamp:16,
        0:3, Id:11/bitstring, 0:18,
        Data:Len/binary, _/binary>>) ->
    #can_pkt{id=Id, data=Data, timestamp=Timestamp}.
于 2011-05-01T19:31:30.230 回答