[erlang-questions] 12B4 dialyzer problem 4
Kostis Sagonas
kostis@REDACTED
Thu Sep 11 14:20:49 CEST 2008
Anthony Shipman wrote:
> I have some functions in a gen_server:
>
> enableConnecting(State, T) ->
> {ok, TRef} = timer:send_after(T, State#state.timerRef),
> State#state{timer = TRef}.
>
> disableConnecting(State) ->
> case State#state.timer of
> undefined ->
> State;
>
> (285) TRef ->
> timer:cancel(TRef),
> State#state{timer = undefined}
> end.
>
> Dialyzer says
>
> muConnector.erl:285: The variable TRef can never match since previous clauses
> completely covered the type 'undefined'
>
> enableConnecting() is definitely reachable so how can this be so?
>
[... Anthony has sent me his complete program in a private mail ...]
In that program I see that disableConnecting/1 is a function which is
local to the module; it's not exported. The only place where it is
called is in a function which reads:
onUp(State) ->
#state{locn = Locn, subscribers = Subs, isUp = Up, waiters = W} =
State,
S1 = if
not Up ->
%% ?INFO_("muConnector: MU is up"),
lists:foreach(fun(Sub) -> Sub!{muUp, Locn} end, Subs),
lists:foreach(fun(From) -> gen_server:reply(From, ok) end, W),
State#state{isUp = true, waiters = []};
true ->
State
end,
disableConnecting(S1).
If one looks closely in this function, she can observe that the 'timer'
field is never initialized so it defaults to 'undefined'. This happens
on all paths to the disableConnecting(S1) call.
Dialyzer has every right to claim that State#state.timer will always be
'undefined' and the second clause (with TRef) will never be reached.
One more subtle bug uncovered.
Kostis
More information about the erlang-questions
mailing list