2

約 6000 行の Erlang コードがあるプロジェクトで、型-spec()注釈がまだない場合、次のことを試しました。

typer --annotate *.erl

*.erlすべてのファイルを注釈付きのファイルに置き換えて実行しました

dialyzer --src -c *.erl

多くの警告が表示されることを期待していましたが (初回はダイアライザーとタイパーの組み合わせを実行しました)、ダイアライザーがレポートしたのは、user_default 内の存在しない関数に対する 2 つの古い呼び出しでした。

デフォルトの警告は他にトリガーされませんでした。

使い方を間違えたのか、それともこのような結果になることが多いのでしょうか。

typer自動注釈ととの組み合わせはdialyzerあまり役に立たないのでしょうか、それとも単に幸運でコードに問題がないのでしょうか?


補足:クラッシュした-spec()ため、3 つまたは 4 つの s をコメントアウトする必要がありました。dialyzer

Erlang R13B04 の Dialyzer v2.2.0 と TypEr バージョン v0.1.7.4 を使用しています。

4

1 に答える 1

3

erlang-bugs リストでバグを報告した副作用として、dialyzer と typer の発明者である Kostis Sagonas から詳細な回答を得ました。

私の側の質問に対して、次の素晴らしい詳細な回答を得ました。

2011 年 5 月 1 日 (日) 午後 5 時 53 分、Kostis Sagonas は次のように書いています。

Peer Stritzinger は次のように書いています。

ところで: typer で --annotate を実行してから、手動で調整された仕様なしでdialyzerを実行したときに警告が表示されないのは正常ですか

はい。実際、typer は、dialyzer の基本的な型推論のフロント エンドにすぎません (つまり、警告識別コンポーネントはありません)。

IMO、取得した仕様を手動で「マッサージ」し、それらの一部についてより多くの情報を提供するつもりがない場合、これを行う意味はほとんどありません。以前のプログラムを見てみましょう。次のように型を導入すると、2 つの << :64, :_*8>> 型が同じ数量を参照していたという事実をより適切に表現できます。

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

チャネルについても同様:

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

そうすれば、スペックはすでに見栄えが良くなります。また、dialyzer/typer には、関数の 2 番目の引数で使用する予定の fun のタイプに関する情報があり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().

また、プレースホルダー型変数を使用して、関数が 2 番目の引数の fun が返す型を何でも返すRという事実を示していることに注意してください。recv/2おそらくこのタイプが何であるかを知っているので、タイプを導入して適切な名前を使用する必要があります。

お役に立てれば、

コスティス

PS。上記に含まれる情報は実際のバグよりも興味深いものであるため、これを erlang-bugs に投稿したのは残念です。

彼はコード フラグメントを参照しているので、バグ レポートに含めました。ここに含めます。次のコード フラグメントは、 によって自動的に注釈が付けられました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 に答える