Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Phoenix.Presence.list/1 raising dialyzer warnings #3027

Closed
nkezhaya opened this issue Aug 18, 2018 · 6 comments
Closed

Phoenix.Presence.list/1 raising dialyzer warnings #3027

nkezhaya opened this issue Aug 18, 2018 · 6 comments
Assignees

Comments

@nkezhaya
Copy link

nkezhaya commented Aug 18, 2018

Environment

  • Elixir 1.7.2
  • Phoenix 1.3.x, master
  • Erlang 21.0.5

Given the following modules:

defmodule MyAppWeb.Presence do
  use Phoenix.Presence,
    otp_app: :my_app,
    pubsub_server: MyAppWeb.PubSub
end
defmodule MyAppWeb.RoomChannel do
  use MyAppWeb, :channel
  use Guardian.Phoenix.Socket

  # def join(args) ...

  @impl true
  def handle_in("new_msg", %{"body" => body}, socket) do
    recipient_id = body["recipient_id"]

    if is_nil(Presence.list(room)[recipient_id]) do
      Chat.conversation_read_by!(conversation, recipient_id, false)

      # Send push notification
      Notifications.broadcast!(:message_created, message: message)
    end
  end
end

The call to Presence.list/1 causes Dialyzer to raise a warning. It can be suppressed by calling: Phoenix.Presence.list(MyAppWeb.Presence, room), but this shouldn't be required.

lib/my_app_web/channels/room_channel.ex:68: The call 'Elixir.MyAppWeb.Presence':list(_room@1::<<_:8,_:_*1>>) will never return since it differs in the 1st argument from the success typing arguments: (#{'__struct__':='Elixir.Phoenix.Socket', 'topic':=#{'__struct__':='Elixir.Phoenix.Socket', 'topic':=#{'__struct__':='Elixir.Phoenix.Socket', 'topic':=map(), _=>_}, _=>_}, _=>_})

@AlexRiedler
Copy link

AlexRiedler commented Aug 18, 2018

Since I was debugging this a bit as well; it seems dialyzer believes the correct type should be:

@spec list(%Phoenix.Socket{
  :topic => %Phoenix.Socket{:topic => %Phoenix.Socket{:topic => map(), _ => _}, _ => _},
  _ => _
}) :: no_return()

However that seems incredibly broken since that would break the type definition of Phoenix Socket itself. Which started to make me believe it was broken in dialyzer (but its hard to know how it's getting to this definition, or how it is being implied AFAIK).

Also if you remove:

def list(%Phoenix.Socket{topic: topic}), do: list(topic)

from the __using__, you get a no_return from dialyzer instead on list/2.

I also noticed:

from pubsub Phoenix.Tracker:

@type presence :: {key :: String.t, meta :: map}

however from Phoenix.Presence:

@type presence :: %{key: String.t, meta: map()}

which is fairly different (AFAIK) in terms of types.

@AndrewDryga
Copy link
Contributor

There is another dialyzer warning in the same module:

apps/talkinto_web/lib/talkinto_web/presence.ex:71:unmatched_return
Expression produces a value of type:

:ignore | {:error, _} | {:ok, pid()} | {:ok, pid(), _}

but this value is unmatched.

I think it comes from c:handle_diff/2.

@axelson
Copy link
Contributor

axelson commented Oct 18, 2018

I ran into this also and I believe it is fixed in phoenixframework/phoenix_pubsub#116 which was released yesterday as part of phoenix_pubsub 1.1.1 https://hex.pm/packages/phoenix_pubsub/1.1.1

@whitepaperclip and @AndrewDryga does using phoenix_pubsub 1.1.1 fix this for you?

@chrismccord
Copy link
Member

This is fixed with the release of Phoenix PubSub 1.1.1 as @axelson has shown, so please update. Thanks!

@nkezhaya
Copy link
Author

@chrismccord @axelson I updated Phoenix PubSub to 1.1.1, and while the original warning is gone, it's been replaced by another:

lib/my_app_web/presence.ex:2: The inferred return type of init/1 ({'ok',#{'node_name':=binary(), 'pubsub_server':=atom(), 'task_sup':='Elixir.MyAppWeb.Presence.TaskSupervisor'}}) has nothing in common with {'error',_} | {'ok',pid()}, which is the expected return type for the callback of the 'Elixir.Phoenix.Presence' behaviour

There's nothing in my presence.ex other than:

defmodule MyAppWeb.Presence do
  use Phoenix.Presence,
    otp_app: :my_app,
    pubsub_server: MyAppWeb.PubSub
end

@nkezhaya
Copy link
Author

(This is on Phoenix 1.3.4 - I haven't checked the 1.4.0 RC yet.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants