Пробег диализера после аннотации с Тайпером не показал никаких предупреждений
-
27-10-2019 - |
Вопрос
В проекте с около 6000 строк кода Erlang, но без типа -spec()
Аннотация еще я попробовал следующее:
typer --annotate *.erl
Я заменил все *.erl
файлы с аннотированными и запускались
dialyzer --src -c *.erl
Я ожидал получить много предупреждений (запустил комбинацию Dialyzer/Typer в первый раз), но после того, как все сообщили, что все диализеры сообщили, что 2 старых вызовов в User_default, которые не существуют.
Никакие другие предупреждения по умолчанию не вызвали.
Я сделал ошибку, используя это или такой обычный результат?
Это комбинация автоматической аннотации с typer
а также dialyzer
Не так полезно или мне просто повезло, и у моего кода нет проблем?
Sidenote: Мне пришлось прокомментировать 3 или 4 -spec()
s Потому что dialyzer
разбился на них.
Я использую Dialyzer V2.2.0 и Typer версию V0.1.7.4 от Erlang R13B04
Решение
В качестве побочного эффекта сообщений об ошибке в списке Erlang-Bugs я получил подробный ответ на это от Kostis Sagonas, изобретателя Dialyzer и Typer.
На мой боковой вопрос я получил следующий отличный и подробный ответ:
На солнце, 1 мая 2011 года в 17:53, Костис Сагонас написал:
Пир Стритцингер написал:
Кстати: нормально ли не получить никаких предупреждений, когда это просто делать -аннотировать в Тайпере, а затем диализер без вручную
Да. Фактически, Тайпер - это всего лишь передняя часть для базового вывода диализатора (т.е. без компонента идентификации предупреждения).
ИМО, в этом не так мало, если вы не намереваетесь вручную «массаж» тех спецификаций, которые вы получаете, и предоставить больше информации для некоторых из них. Взгляните на свою предыдущую программу. Тот факт, что два <: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
Возвращает любой тип, веселье во втором аргументе возвращается. Вы, вероятно, знаете, что это за тип, поэтому вы также должны представить для него тип и использовать его правильное имя.Надеюсь это поможет,
Костис
Пса Жаль, что вы опубликовали это в Erlang-Bugs, так как информация, содержащаяся в вышеизложенном, является более интересной, чем фактическая ошибка.
Поскольку он ссылается на фрагмент кода, я включил в свой отчет об ошибках, я включаю его здесь. Следующий фрагмент кода был автоматически аннотирован 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}.