I am trying to clean up all of the dialyzer warnings in my project, and I"m having a hard time fixing this last error.
lib/rtmp/protocol/handler.ex:204: The pattern #{‘message_type_id’:=19, ‘struct’:=‘Elixir.Rtmp.Protocol.RawMessage’} can never match the type #{‘struct’:=‘Elixir.Rtmp.Protocol.RawMessage’, ‘deserialization_system_time’:=‘nil’, ‘force_uncompressed’:=‘false’, ‘message_type_id’:=8 | 9 | 20, ‘payload’:=<<>>, ‘stream_id’:=non_neg_integer(), ‘timestamp’:=non_neg_integer()}
That section of code is:
defp get_csid_for_message_type(%RawMessage{message_type_id: 1}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 2}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 3}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 4}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 5}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 6}), do: 2
defp get_csid_for_message_type(%RawMessage{message_type_id: 18}), do: 3
defp get_csid_for_message_type(%RawMessage{message_type_id: 19}), do: 3
defp get_csid_for_message_type(%RawMessage{message_type_id: 9}), do: 21
defp get_csid_for_message_type(%RawMessage{message_type_id: 8}), do: 20
defp get_csid_for_message_type(%RawMessage{message_type_id: _}), do: 6
Line 204 is the defp get_csid_for_message_type(%RawMessage{message_type_id: 19}), do: 21
This function is used in the following function:
def handle_cast({:send_message, message}, state) do
raw_message = RawMessage.pack(message)
csid = get_csid_for_message_type(raw_message)
# ... rest snipped for brevity
end
So essentially it’s taking a %DetailedMessage{}
, passing it into a RawMessage.pack()
function to turn it into a %RawMessage{}
, and then trying to get the csid for it. The definition for pack()
is:
@doc "Packs a detailed RTMP message into a serializable raw message"
@spec pack(DetailedMessage.t) :: __MODULE__.t
def pack(message = %DetailedMessage{}) do
{:ok, payload} = message.content.__struct__.serialize(message.content)
%__MODULE__{
timestamp: message.timestamp,
stream_id: message.stream_id,
message_type_id: get_message_type(message.content.__struct__),
payload: payload,
force_uncompressed: message.force_uncompressed
}
end
# WARNING: We have to match on the module names themselves instead of
# a normal struct pattern match, otherwise we have circular references
# during compilation and it failes due to the callbacks
defp get_message_type(Rtmp.Protocol.Messages.SetChunkSize), do: 1
defp get_message_type(Rtmp.Protocol.Messages.Abort), do: 2
defp get_message_type(Rtmp.Protocol.Messages.Acknowledgement), do: 3
defp get_message_type(Rtmp.Protocol.Messages.UserControl), do: 4
defp get_message_type(Rtmp.Protocol.Messages.WindowAcknowledgementSize), do: 5
defp get_message_type(Rtmp.Protocol.Messages.SetPeerBandwidth), do: 6
defp get_message_type(Rtmp.Protocol.Messages.AudioData), do: 8
defp get_message_type(Rtmp.Protocol.Messages.VideoData), do: 9
defp get_message_type(Rtmp.Protocol.Messages.Amf0Data), do: 18
defp get_message_type(Rtmp.Protocol.Messages.Amf0Command), do: 20
Also, the type definition for RawMessage.t
is:
@type t :: %__MODULE__{
timestamp: non_neg_integer(),
message_type_id: non_neg_integer(),
stream_id: non_neg_integer(),
force_uncompressed: false,
deserialization_system_time: pos_integer() | nil,
payload: <<>>
}
So as you can see I’m trying to tell dialyzer that RawMessage.message_type_id
can be any non-negative integer yet dialyzer’s error message seems to be saying it thinks that message_type_id
can only be 8, 9, or 20. What’s even more odd is that the get_csid_for_message_type
function deals with many other situations where the message type id is not 8, 9, or 20 and yet it only seems to barf at the one where the number is 19.
Anyone have any insights on what might be causing this cause I’ve been staring at this for 30 minutes completely stumped.
If anyone wants to try for themselves you should be able to try it with this commit