[erlang-questions] Dialyzer: Why do I get a 'will never return success typing error' with this recursive function?
Fri Feb 24 18:36:43 CET 2012
On Fri, Feb 24, 2012 at 12:07 PM, Kostis Sagonas <kostis@REDACTED> wrote:
> 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.]
Likely, as in my case, because | is often OR in other languages. This
is what I was incorrectly assuming, that I was specifying that the
function returns nothing OR it returns ok.
(Yes, now looking at the docs they do clearly indicate | is union).
> 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.
So my case where I do want the atypical behaviour to loop with some
args and no with others, I should forgo the spec and ignore the
Dialyzer warning? There is no way I can state via aspecs that this is
indeed the intent of the function?
More information about the erlang-questions