[erlang-questions] Dyalizer warnings for too wide return type
Kostis Sagonas
kostis@REDACTED
Sun Oct 17 18:11:59 CEST 2010
Vincent de Phily wrote:
> On Tuesday 12 October 2010 08:48:57 Alexey Romanov wrote:
>> One problem I have with Dialyzer is that it complains about cases
>> where the return type specified is too wide.
>>
>> E.g.
>>
>> -type handle_cast_return() :: {noreply, tuple()} | {noreply, tuple(),
>> integer()} | {stop, any(), tuple()}.
>> -spec handle_cast(any(), tuple()) -> handle_cast_return().
>> handle_cast(_Msg, State) ->
>> {noreply, State}.
>>
>> The definition says that handle_cast returns what it is supposed to
>> return according to behaviour, but it gives this warning:
> [...]
>> the given specification satisfies it, and shouldn't result in a
>> warning. Or at least, there should be an option to turn this set of
>> warnings off, and I don't see one in
>> `dialyzer -Whelp`.
>
> It sounds like -Wunderspecs or -Woverspecs would do that, but that doesn't
> seem to work. Actually it looks like (contrary to documentation) -Wunderspecs
> is on by default and we actually need a -Wno_underspecs option.
>
> But a global no_underspec for the program sounds dangerous too (you'll hide
> actual underspecs which should be fixed). Maybe dialyzer could ease the pain
> by handly behaviour spec specially ?
>
>> -spec some_test() -> boolean().
>> some_test() -> false. %% TODO implement later
>>
>> %% in a different module
>> foo() ->
>> case m1:some_test() of
>> true -> ...
>> false -> ...
>> end.
>>
>> In addition to the warning about some_test() I get warnings about
>> foo(): "Pattern 'true' can never match type 'false' ", any functions
>> called only from the 'true' branch are reported to be unused, etc.
>> While these warnings are correct, they ignore my specification for
>> some_test(). Can Dialyzer be forced to prefer the return type given in
>> the spec over the` one it infers?
>
> Yes, that annoys me as well. I understand the warning for the some_spec
> function, but I think it shouldn't trickle down to the foo function. I have
> another use-case where I recompile a module at runtime but provide an initial
> implementation that always returns false.
I could have written a much longer reply in this thread, but I'll keep
this reply a bit short with the risk of sounding a bit impolite. This is
not my intention.
The whole discussion above is a bit naive, but perhaps this is primarily
my fault because there is no document that explains dialyzer's decisions
and philosophy in general terms. For a long time now I wanted to write a
"dialyzer FAQ". I hope I can come around to that pretty soon.
Anyway, the short answer is that dialyzer will never do what users may
initially think it would be better if it did. The only information that
dialyzer has to work with is the code and whenever it finds something
that is a discrepancy between what the code does and what the programmer
claims it does (e.g. in a spec) it spits a warning about it. Dialyzer
cannot be in the minds of programmers and what's their ultimate
intention even if they add "%% TODO implement later" comments :-)
So, my reply to Alexey's message is that in a situation like the one he
describes the proper action is to either comment out the true case in
foo's code or realize that now is the time for this "later".
Now, having written all these, there is a dialyzer option that we have
primarily added for internal debugging purposes, but may come in handy
in situations like that. If you want dialyzer to do its analysis based
on success typings only and ignore the specs of the analyzed modules,
you can use the option '--no_spec'.
But there is no option "trust the specs, please" for cases where
dialyzer can determine that they do not correspond to the code.
Whenever you want to do that, simply don't use dialyzer!
> I'd like dializer to trust me when I declare my interface, even if the
> implementation doesn't match that. Actually, maybe we could make the case that
> non-exported functions must have an exact spec whereas exported function can
> have a spec that is more allowing than the implementation ?
Sorry, but I firmly believe that this last part is wrong. Having
published interfaces that do not correspond to the implementation is not
a good idea. Among other things, what sort of confidence do you have
that the client code works ok? How do you test things in this situation?
Cheers,
Kostis
More information about the erlang-questions
mailing list