开发者

Run of dialyzer after annotation with typer did not show any warnings

In a project with about 6000 lines of Erlang code but no type -spec() annotation yet I tried the following:

typer --annotate *.erl

The I replaced all *.erl files with the annotated ones and ran

dialyzer --src -c *.erl

I expected to get lots of warnings (ran the dialyzer/typer combination the first time) but after doing its thi开发者_开发技巧ng all dialyzer reported were 2 old calls in user_default to meanwhile nonexistent functions.

No other of the default warnings did trigger.

Did I make a mistake using it or is a result like this common?

Is the combination of auto annotation with typer and dialyzer not so useful or am I just lucky and my code doesn't have issues?


Sidenote: I had to comment out 3 or 4 -spec()s because dialyzer crashed on them.

I'm using Dialyzer v2.2.0 and TypEr version v0.1.7.4 from Erlang R13B04


As a side effect of reporting a bug on the erlang-bugs list I got an detailed answer this from Kostis Sagonas, the inventor of dialyzer and typer.

To my side question I got the following great and detailed answer:

On Sun, May 1, 2011 at 5:53 PM, Kostis Sagonas wrote:

Peer Stritzinger wrote:

BTW: is it normal not to get any warnings when just doing --annotate in typer and then dialyzer with no manually tweaked spec's

Yes. In fact, typer is just a front end for dialyzer's basic type inference (i.e. without the warning identification component).

IMO, there is very little point in doing this if you do not intend to manually "massage" the specs that you get and provide more info for some of them. Take a look at your previous program. The fact that the two <<:64,:_*8>> types were referring to the same quantity could be expressed better if you introduced a type as in:

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

Similarly for channel:

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

and then the spec would already look better. Also, dialyzer/typer has no info on what type of fun you intend to use in the second argument of function recv/3 but you do! From the code it is clear that it takes #can_pkt{} record, so why don't you add appropriate types to its fields and introduce a type for it?

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

then the specs can look much better:

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

and note that I've used a placeholder type variable R to denote the fact that function recv/2 returns whatever type the fun in its second argument returns. You probably know what this type is so you should also introduce a type for it and use its proper name.

Hope this helps,

Kostis

PS. It's a pity you posted this in erlang-bugs as the information contained in the above is IMO more interesting than the actual bug.

Since he refers to a code fragment, I included in my bug report, I include it here. The following code fragment was automatically annotated by 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}.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜