Closed as not planned
Description
Elixir and Erlang/OTP versions
Erlang/OTP 27 [erts-15.0] [source] [64-bit] [smp:6:6] [ds:6:6:10] [async-threads:1] [jit:ns]
Elixir 1.17.1 (compiled with Erlang/OTP 27)
Operating system
Ubuntu 24.04
Current behavior
In our codebase we have a guard defined like so:
defguardp conn_scope(conn, target)
when is_atom(target) and is_struct(conn, Conn) and
is_atom(conn.assigns.auth_profile.scope) and
conn.assigns.auth_profile == target
defguardp session_scope(session, target)
when is_atom(target) and is_struct(session, Session) and
is_atom(session.scope) and
session.scope == target
defguard auth_scope(conn, target)
when conn_scope(conn, target) or session_scope(conn, target)
so that we can use the guard auth_scope
either with a parameter of type Conn
or a parameter of type Session
, and you can see that we use is_struct
to restrict further guards to access the correct members of the appropriate struct.
With Elixir 1.17 the compiler gives the following warning:
warning: unknown key .assigns in expression:
session.assigns
where "session" was given the type:
# type: dynamic(%DataLayer.Session{
acked_server_sequence: term(),
app_id: term(),
authenticated: term(),
default_api_version: term(),
expires_at: term(),
expiry_timer: term(),
external_user_id: term(),
id: term(),
permissions: term(),
protocol_version: term(),
scope: term(),
sdk_name: term(),
server_sequence: term(),
socket_pid: term(),
transport: term(),
user_id: term()
})
# from: lib/backend_web/calls/conversation_calls.ex:110
%DataLayer.Session{app_id: app_id} = session
typing violation found at:
│
112 │ when auth_scope(session, :app) do
│ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
│
└─ lib/backend_web/calls/conversation_calls.ex:112: BackendWeb.ConversationCalls.delete/2
because it checks also for the guards of the other data structure.
Expected behavior
No warning being emitted, because is_struct
narrows down subsequent guards to only 1 data type.