[erlang-questions] Dialyzer: Why do I get a 'will never return success typing error' with this recursive function?
Fri Feb 24 18:07:34 CET 2012
On 02/24/2012 02:24 PM, Jeremy Raymond wrote:
> Thanks for the info. I'm using R15B. Why wouldn't this spec help
> Dialyzer avoid the warning?
> -spec test(noloop | loop) -> no_return() | ok.
Because this spec is wrong and non-sensical and dialyzer is clever
enough to see this ;)
First of all your spec does not make sense. Types as sets of Erlang
terms. no_return() is the empty set; 'ok' is the singleton set
containing the atom 'ok' and the union operator | is set union. So your
return type no_return | 'ok' is actually indistinguishable from 'ok'.
Lesson #1: do not ever write no_return() | other_type(). Dialyzer will
treat this as if you had written other_type().
[Aside: for some reason, this is a very common mistake.]
Second, for your first program, dialyzer's type inference is strong
enough to infer that your function will only return a value when its
argument is 'noloop'. So you are effectively lying in the argument type
also. Dialyzer discovers this and has reasonable reasons not to like
your spec, so it totally ignores it keeping the information that it has
inferred, namely that the success typing of this function is:
-spec test('noloop') -> 'ok'.
This explains the warning you get in your first program.
Lesson #2: do not spec function args with terms for which the function
will not return any value.
Finally, as to why you do not get a warning in your second program, the
answer is very simple: Dialyzer never promised to find all errors in
your code; the only thing that it claims is that when it does give you
some warning it's a correct one.
More information about the erlang-questions