Запуск диализатора после аннотации с typer не показывал никаких предупреждений - PullRequest
2 голосов
/ 01 мая 2011

В проекте с около 6000 строк кода Erlang, но без аннотации типа -spec() я попробовал следующее:

typer --annotate *.erl

Я заменил все *.erl файлы на аннотированные и запустил

dialyzer --src -c *.erl

Я ожидал получить много предупреждений (запускал комбинацию диализатор / типизатор в первый раз), но после выполнения этой операции все сообщения о диализаторе были 2 старыми вызовами в user_default, в то время как несуществующие функции.

Никакие другие предупреждения по умолчанию не сработали.

Я допустил ошибку, используя это, или результат, как этот распространенный?

Не слишком ли полезна комбинация автоматической аннотации с typer и dialyzer или мне просто повезло, и у моего кода нет проблем?


Sidenote: Я должен был закомментировать 3 или 4 -spec() с, потому что dialyzer разбился на них .

Я использую Dialyzer v2.2.0 и TypEr версии v0.1.7.4 от Erlang R13B04

1 Ответ

3 голосов
/ 01 мая 2011

В качестве побочного эффекта сообщения об ошибке в списке ошибок erlang, я получил подробный ответ на этот вопрос от Костиса Сагонаса, изобретателя диализатора и typer.

На мой дополнительный вопрос я получил следующий отличный иподробный ответ:

На Солнце, 1 мая 2011 года в 17:53, Костис Сагонас написал:

Пир Стрицингер написал:

Кстати: нормально ли не получать никаких предупреждений, когда просто выполняешь --annotate в typer, а затем в диализаторе без подправленных вручную спецификаций

Да.На самом деле, typer - это просто интерфейс для определения базового типа диализатора (т. Е. Без компонента идентификации предупреждения).

IMO, в этом нет особого смысла, если вы не собираетесь вручную "массировать"спецификации, которые вы получаете и предоставляете больше информации для некоторых из них.Посмотрите на вашу предыдущую программу.Тот факт, что два типа << <em>: 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 возвращает любой тип, который возвращает fun во втором аргументе.Вы, вероятно, знаете, что это за тип, поэтому вам также следует ввести для него тип и использовать его собственное имя.

Надеюсь, это поможет,

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}.
...