Запуск диализатора после аннотации с 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}.
Другие вопросы по тегам