Запуск диализатора после аннотации с typer не показывал никаких предупреждений
В проекте около 6000 строк кода Эрланга, но без типа -spec()
аннотации еще пробовал следующее:
typer --annotate *.erl
То я заменил все *.erl
файлы с аннотированными и побежал
dialyzer --src -c *.erl
Я ожидал получить много предупреждений (запускал комбинацию диализатор / типизатор в первый раз), но после выполнения этой задачи все диализаторы сообщали о двух старых вызовах в user_default, в то время как несуществующие функции.
Никакие другие предупреждения по умолчанию не сработали.
Я сделал ошибку, используя это или результат как этот распространенный?
Является ли сочетание автоаннотации с typer
а также dialyzer
не очень полезно или мне просто повезло, и у моего кода нет проблем?
Sidenote: я должен был закомментировать 3 или 4 -spec()
потому что dialyzer
разбился на них.
Я использую Dialyzer v2.2.0 и TypEr версии v0.1.7.4 от Erlang R13B04
1 ответ
В качестве побочного эффекта сообщения об ошибке в списке ошибок erlang я получил подробный ответ на этот вопрос от Kostis Sagonas, изобретателя диализатора и typer.
На мой дополнительный вопрос я получил следующий большой и подробный ответ:
В воскресенье 1 мая 2011 года в 5:53 вечера Костис Сагонас написал:
Пер Стритцингер написал:
Кстати: это нормально, чтобы не получать никаких предупреждений, когда просто выполняешь --annotate в typer, а затем в диализаторе без настроек, настроенных вручную
Да. На самом деле, Typer - это просто интерфейс для базового вывода типа диализатора (т.е. без компонента идентификации предупреждения).
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
возвращает любой тип веселья во втором аргументе. Вы, вероятно, знаете, что это за тип, поэтому вам также следует ввести для него тип и использовать его собственное имя.Надеюсь это поможет,
Kostis
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}.