[erlang-questions] Dialyzer: Why do I get a 'will never return success typing error' with this recursive function?

Kostis Sagonas kostis@REDACTED
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.

Short answer:

  Because this spec is wrong and non-sensical and dialyzer is clever 
enough to see this ;)


Long answer:

  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.

Kostis



More information about the erlang-questions mailing list