Why Erlang Dialyzer cannot find type error in the following code? -


free_vars_in_dterm({var, v}) -> {var, v}; cannot type check, however, dialyzer says ok. $ dialyzer *erl checking whether plt ~/.dialyzer_plt up-to-date... yes proceeding analysis... done in 0m0.66s done (passed successfully)

code below:

-module(formulas).  -type formulas() :: {predicate(), [dterm()]}                   | {'~', formulas()}                   | {'&', formulas(), formulas()}                   | {'|', formulas(), formulas()}                   | {'->', formulas(), formulas()}                   | {'<->', formulas(), formulas()}                   | {'exist', variable(), formulas()}                   | {'any', variable(), formulas()}.  -type dterm() :: constant()                | variable()                | {func(), [dterm()]}.  -type constant() :: {const, atom()}                   | {const, integer()}.  -type variable() :: {var, atom()}.  -type func() :: {function,                  function_name::atom(),                  arity::integer()}.  -type predicate() :: {predicate,                       predicate_name::atom(),                       arity::integer()}.   -include_lib("eunit/include/eunit.hrl").  -export([is_ground/1, free_vars/1, is_sentence/1]).  -spec is_ground(formulas()) -> boolean(). is_ground({_, {var, _}, _}) -> false; is_ground({{predicate, _, _}, terms}) ->     lists:all(fun is_ground_term/1, terms); is_ground(formulas) ->     ts = tuple_size(formulas),     lists:all(fun is_ground/1, [element(i, formulas)                                 || <- lists:seq(2, ts)]).  -spec is_ground_term(dterm()) -> boolean(). is_ground_term({const, _}) -> true; is_ground_term({var, _}) -> false; is_ground_term({{function, _, _}, terms}) ->     lists:all(fun is_ground_term/1, terms).   -spec is_sentence(formulas()) -> boolean(). is_sentence(formulas) ->     sets:size(free_vars(formulas)) =:= 0.  -spec free_vars(formulas()) -> sets:set(variable()). free_vars({{predicate, _, _}, dterms}) ->     join_sets([free_vars_in_dterm(dterm)                || dterm <- dterms]); free_vars({_qualify, {var, v}, formulas}) ->     sets:del_element({var, v}, free_vars(formulas)); free_vars(compound_formulas) ->     tp_size = tuple_size(compound_formulas),     join_sets([free_vars(element(i, compound_formulas))                || <- lists:seq(2, tp_size)]).  -spec free_vars_in_dterm(dterm()) -> sets:set(variable()). free_vars_in_dterm({const, _}) -> sets:new(); free_vars_in_dterm({var, v}) -> {var, v}; free_vars_in_dterm({{function, _, _}, dterms}) ->     join_sets([free_vars_in_dterm(dterm)                || dterm <- dterms]).  -spec join_sets([sets:set(t)]) -> sets:set(t). join_sets(set_list) ->     lists:foldl(fun (t, acc) -> sets:union(t, acc) end,                 sets:new(),                 set_list). 

first short answer, using dialyzer's maxims :

  1. dialyzer never wrong. (recited erlang programmers)
  2. dialyzer never promised find errors in code. (not famous)

maxim number 2 (admittedly not satisfying) "standard" answer "why dialyzer didn't catch error" question.


more explanatory answer:

dialyzer's analysis return values of functions doing over-approximations. result, value included in types should considered "maybe returned" value. has unfortunate side-effect values going returned (such {var, v} tuple) considered "maybe returned". dialyzer must guarantee maxim 1 (never wrong), in cases unexpected value "may returned" not give warning, unless none of specified values can returned. last part checked @ level of entire function, , since in example of clauses indeed return sets, no warnings generated.


Comments

Popular posts from this blog

javascript - Clear button on addentry page doesn't work -

c# - Selenium Authentication Popup preventing driver close or quit -

tensorflow when input_data MNIST_data , zlib.error: Error -3 while decompressing: invalid block type -