Domanda

In un progetto con circa 6000 righe di codice Erlang ma nessun tipo -spec() annotazione eppure ho provato quanto segue:

typer --annotate *.erl

Io ho sostituito tutto *.erl file con quelli annotati e eseguiti

dialyzer --src -c *.erl

Mi aspettavo di ottenere molti avvertimenti (ha eseguito la combinazione Dialyzer/Typer per la prima volta) ma dopo aver fatto la sua cosa che tutti i Dialyzer segnalavano erano 2 vecchie chiamate in User_Default a nel frattempo funzioni inesistenti.

Nessun altro degli avvertimenti predefiniti si è innescato.

Ho commesso un errore usandolo o è un risultato come questo comune?

È la combinazione di annotazione automatica con typer e dialyzer Non così utile o sono solo fortunato e il mio codice non ha problemi?


Sidenote: ho dovuto commentare 3 o 4 -spec()s perché dialyzer si è schiantato su di loro.

Sto usando Dialyzer V2.2.0 e Typer versione v0.1.7.4 da Erlang R13B04

È stato utile?

Soluzione

Come effetto collaterale della segnalazione di un bug nell'elenco Erlang-Bugs, ho ricevuto una risposta dettagliata da Kostis Sagonas, l'inventore di Dialyzer e Typer.

Alla mia domanda ho ricevuto la seguente risposta fantastica e dettagliata:

Su Sun, 1 maggio 2011 alle 17:53, Kostis Sagonas ha scritto:

Peer Stritzinger ha scritto:

Btw: è normale non ottenere avvertimenti quando lo fai: annota in typer e poi dializzatore senza specifiche ottimizzate manualmente

Sì. In effetti, Typer è solo un front -end per l'inferenza di tipo base di Dialyzer (cioè senza il componente di identificazione di avviso).

IMO, c'è pochissimo punto nel farlo se non si intende "massaggiare" manualmente le specifiche che ottieni e fornire maggiori informazioni per alcune di esse. Dai un'occhiata al tuo programma precedente. Il fatto che i due <:64,: _*8 >> i tipi si riferivano alla stessa quantità poteva essere espresso meglio se si introduceva un tipo come in:

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

Allo stesso modo per canale:

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

E poi le specifiche sarebbero già migliori. Inoltre, Dialyzer/Typer non ha informazioni sul tipo di divertimento che intendi utilizzare nel secondo argomento della funzione recv/3 Ma lo fai! Dal codice è chiaro che ci vuole #can_pkt{} Registra, quindi perché non aggiungi tipi appropriati ai suoi campi e introduci un tipo per questo?

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

Quindi le specifiche possono apparire molto meglio:

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

e nota che ho usato una variabile di tipo segnaposto R per indicare il fatto che la funzione recv/2 Restituisce qualunque tipo di divertimento nel suo secondo argomento ritorna. Probabilmente sai cos'è questo tipo, quindi dovresti anche introdurre un tipo per esso e usarlo.

Spero che sia di aiuto,

Kostis

Ps. È un peccato che tu abbia pubblicato questo in Erlang-Bugs poiché le informazioni contenute in quanto sopra sono più interessanti del bug reale.

Dato che si riferisce a un frammento di codice, ho incluso nel mio rapporto di bug, lo includo qui. Il seguente frammento di codice è stato automaticamente annotato da 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}.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top