[erlang-questions] Dialyzer bug or some problem with my code

Anthony Molinaro <>
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                           <>


More information about the erlang-questions mailing list