[erlang-questions] Dialyzer bug or some problem with my code
Anthony Molinaro
anthonym@REDACTED
Tue Mar 22 04:28:50 CET 2011
On Tue, Mar 22, 2011 at 02:26:46AM +0200, Kostis Sagonas wrote:
> Anthony Molinaro wrote:
> >Hi,
> >
> > Not sure if this is a bug or not, but the attached file exhibits the
> >following.
> >
> >% erlc tmp.erl
> >% erl -eval 'tmp:test(), init:stop()' -noshell
> > All 2 tests passed.
> >% dialyzer -Wno_opaque tmp.erl
> > Checking whether the PLT /Users/molinaro/.dialyzer_plt is up-to-date... yes
> > Proceeding with analysis...
> >tmp.erl:19: Function key_in_dict/2 has no local return
> >Unknown functions:
> > eunit:test/1
> > done in 0m0.63s
> >done (warnings were emitted)
> >
> >Using R14B02. As far as I can tell the key_in_dict function always returns
> >so I'm not sure why it would have no local return. I can always work around
> >with -Wno_return but I already don't like the fact that I have to work around
> >dict being an opaque type with -Wno_opaque (is that ever going to get fixed?).
>
> You've put yourself in a corner and now you are wondering why you
> are there...
>
> The option -Wno_opaque does not mean what you think it means: it
> simply shuts off all dialyzer *warnings* about opacity violations in
> your code. But it does not make dialyzer change its default
> behavior, which is to consider all opacity violations as failures.
>
> Without this option, dialyzer complains that:
>
> tmp.erl:11: The call tmp:key_in_dict(A::any(),Dict::tuple()) does
> not have an opaque term of type dict() as 2nd argument
> tmp.erl:19: Function key_in_dict/2 has no local return
> tmp.erl:20: The call
> dict:is_key(Key::maybe_improper_list(),Dict::tuple()) does not have
> an opaque term of type dict() as 2nd argument
>
> and it's exactly the warning in line 20 which makes dialyzer think
> that you are doing something wrong there. For better or worse,
> dict() is defined as an opaque data type, in the Erlang
> documentation also, which means that you should not really inspect
> its structure with type tests and element/1 like you do in your
> code:
Okay, that's unfortunate. I realize I'm peeking behind the curtain here but
what other choice do I have without any sort of dict:is_dict/1 function.
> In your case you can cheat a bit and "have your cake and eat it
> too", if you are willing to come to terms that the "let it fail"
> philosophy is actually a good design principle and your code should
> not just return false if you happen to pass something unexpected to
> the second argument of in_thing/2. You can then write your code as:
>
> in_thing (A, B) ->
> case B of
> List when is_list (B) -> % IMO: this should read is_list(List) here
> key_in_list (A, List);
> Dict ->
> key_in_dict (A, Dict)
> end.
The problem here, is this was just a simplified example in the real code I
do do something in the third case, so reordering in this way won't quite
help me. I guess I can just -Wno_opaque -Wno_return for the moment :(
Maybe the OTP team can add an is_dict/1 at some point. Seems like most of
the other opaque types have a function to determine if a random term is
of that type. The code would be slightly more convoluted as it would
be nested conditionals like
in_thing (A, B) ->
case dict:is_dict (B) of
true ->
key_in_dict (A, B);
false ->
case B of
List when is_list (List) ->
key_in_list (A, B);
_ ->
false
end
end.
Although not the cleanest at least it should dialyze correctly, and if I
wanted to support additional types (for instance maybe I want to allow a
set of some sort, I could add it using the is_set/1 function call).
Looking through the standard data structures I see that
array:is_array/1
gb_sets:is_set/1
ordset:is_set/1
queue:is_queue/1
sets:is_set/1
all exists, but these are missing
dict:is_dict/1
gb_trees:is_gb_tree/1
orddict:is_orddict/1
Is there any reason these haven't been added to OTP yet? Something about
these last three structures which have kept them from getting a function
to determine if a term is of the given type? (they all seem to be a
dictionary like structure, so maybe something about dict structures means
we can't have an is_dict/1?).
Just wondering,
-Anthony
--
------------------------------------------------------------------------
Anthony Molinaro <anthonym@REDACTED>
More information about the erlang-questions
mailing list