Почему Dialyzer не считает этот код неверным?

Я создал приведенный ниже фрагмент на основе этого руководства. Последние две строки(feed_squid(FeederRP)иfeed_red_panda(FeederSquid))явно нарушают определенные ограничения, но Dialyzer находит их нормальными. Это очень разочаровывает, потому что это именно тот тип ошибки, который я хочу поймать с помощью инструмента, выполняющего статический анализ.

Объяснение есть в туториале:

Before the functions are called with the wrong kind of feeder, they're first called with the right kind. As of R15B01, Dialyzer would not find an error with this code. The observed behaviour is that as soon as a call to a given function succeeds within the function's body, Dialyzer will ignore later errors within the same unit of code.

В чем причина такого поведения? Я понимаю, что философия успешной печати заключается в том, чтобы «никогда не кричать волком», но в текущем сценарии Dialyzer просто игнорирует преднамеренно определенные спецификации функций (после того, как увидит, что функции были вызваны правильно ранее ). Я понимаю, что код не приводит к сбою во время выполнения. Могу ли я каким-то образом заставить Dialyzer всегда серьезно относиться к моим функциональным спецификациям? Если нет, есть ли инструмент, который может это сделать?

-module(zoo).
-export([main/0]).

-type red_panda() :: bamboo | birds | eggs | berries.
-type squid() :: sperm_whale.
-type food(A) :: fun(() -> A).

-spec feeder(red_panda) -> food(red_panda());
            (squid) -> food(squid()).
feeder(red_panda) ->
    fun() ->
            element(random:uniform(4), {bamboo, birds, eggs, berries})
    end;
feeder(squid) ->
    fun() -> sperm_whale end.

-spec feed_red_panda(food(red_panda())) -> red_panda().
feed_red_panda(Generator) ->
    Food = Generator(),
    io:format("feeding ~p to the red panda~n", [Food]),
    Food.

-spec feed_squid(food(squid())) -> squid().
feed_squid(Generator) ->
    Food = Generator(),
    io:format("throwing ~p in the squid's aquarium~n", [Food]),
    Food.

main() ->
    %% Random seeding
    <> = crypto:rand_bytes(12),
    random:seed(A, B, C),
    %% The zoo buys a feeder for both the red panda and squid
    FeederRP = feeder(red_panda),
    FeederSquid = feeder(squid),
    %% Time to feed them!
    feed_squid(FeederSquid),
    feed_red_panda(FeederRP),
    %% This should not be right!
    feed_squid(FeederRP),
    feed_red_panda(FeederSquid).

5
задан Attila Kun 7 August 2012 в 18:08
поделиться