Understanding the use of :erlang.phash2(1, 1) in genserver's handle_call function

      def handle_call(msg, _from, state) do
        proc =
          case Process.info(self(), :registered_name) do
            {_, []} -> self()
            {_, name} -> name
          end

        # We do this to trick Dialyzer to not complain about non-local returns.
        case :erlang.phash2(1, 1) do
          0 ->
            raise "attempted to call GenServer #{inspect(proc)} but no handle_call/3 clause was provided"

          1 ->
            {:stop, {:bad_call, msg}, state}
        end
      end

The :erlang.phash2(1, 1) returns 0 every time I run the function in my iex. So, why not move the raise function out of the case block and remove the case block

1 Like

It’s right there:. “we do this to trick dialyzer…”

3 Likes

hmm. so if that is just to suppress dialyzer then could we write it down like this?

case :erlang.phash2(1, 1) do
          0 ->
            raise "attempted to call GenServer #{inspect(proc)} but no handle_call/3 clause was provided"

          _ ->
            nil
        end

Then dialyzer would probably complain about nil violating the contract for handle_call.

1 Like

i think i get it now.

Since handle_call is a function that is called in other module (if not implemented/overried) it’s a non local return.

So, it needs to return atleast something like the raise or the tuple.

1 Like