[erlang-questions] Recent OTP dev branch dialyzer changes (when-constraints)

Jesper Louis Andersen jesper.louis.andersen@REDACTED
Sat May 21 17:30:25 CEST 2011


PRELIMINARIES

In the commit,

git show 76ca320fd37cecdcf225ddcc094bc72a607b0453 queue.erl

commit 76ca320fd37cecdcf225ddcc094bc72a607b0453
Author: Hans Bolinder <hasse@REDACTED>
Date:   Fri May 6 15:11:15 2011 +0200

    Types and specifications have been modified and added

we have the following hunk change:

@@ -133,7 +146,10 @@ in_r(X, Q) ->
 %% Take from head/front
 %%
 %% O(1) amortized, O(len(Q)) worst case
--spec out(queue()) -> {'empty' | {'value',term()}, queue()}.
+-spec out(Q1) -> Result when
+      Q1 :: queue(),
+      Q2 :: queue(),
+      Result :: {{value, Item :: term()}, Q2} | {empty, Q1}.
 out({[],[]}=Q) ->
     {empty,Q};
 out({[V],[]}) ->

QUESTION:

I have not seen this style before, and EEP-008 / The Reference
documentation makes little reason as to why one would want to change
the "polarity" from positive to negative in the spec constraint.

* What is the reason for the change? I think the change better
reflects the style of other user documentation which is a nice
welcome.

* I am asking because I don't know why the dialyzer complains in my
code. I have a recent branch with the following code:

-record(proc_info, {
	  receiver_q :: queue(),
	  sender_q   :: queue()
}).
-opaque t() :: #proc_info{}.
-export_type([t/0]).
...
-spec dequeue_receiver(t()) -> {ok, term(), t()} | empty.
dequeue_receiver(#proc_info { receiver_q = RQ } = PI) ->
    case queue:out(RQ) of
        {{value, Item}, NQ} ->
            {ok, Item, PI#proc_info { receiver_q = NQ }};
        {empty, _Q} ->
            empty
    end.

which uses the queue:out/2 call. And the dialyzer complains:

utp_process.erl:49: The specification for
utp_process:dequeue_receiver/1 states that the function might also
return {'ok',_,utp_process:t()} but the inferred return is 'empty'

This puzzles me! Clearly queue:out/2 may return '{empty, queue()}'. Is
the dialyzer so strong it guesses RQ is *never* anything but empty?
This is odd because if I look at coverage from my test runs, both
cases are covered (cue bad formatting if you have a non-monospaced
font):

        |  dequeue_receiver(#proc_info { receiver_q = RQ } = PI) ->
124304..|      case queue:out(RQ) of
        |          {{value, Item}, NQ} ->
   151..|              {ok, Item, PI#proc_info { receiver_q = NQ }};
        |          {empty, _Q} ->
124153..|              empty
        |      end.

also note that there is only one call-site of dequeue_receiver/1,
which leads me to think the dialyzer is wrong here, even though I know
the dialyzer is *always right*(tm) :)

VERSION OF ERLANG/OTP: Very recent:

jlouis@REDACTED:~/Projects/otp$ git describe
OTP_R14B02-625-g5f7fa62

Also, ask if more source in my project is needed. If there is any
interest I'll try to boil it down to a minimal example.


-- 
J.



More information about the erlang-questions mailing list