La corsa di dializer dopo l'annotazione con Typer non ha mostrato avvertimenti
-
27-10-2019 - |
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
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 funzionerecv/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}.