-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
[Dialyzer] false positive, "pattern will never match" on interaction with :queue
#7632
Comments
If I'm reading Qex's code correctly, the @spec reverse(t) :: t
def reverse(%__MODULE__{data: q}) do
%__MODULE__{data: :queue.reverse(q)}
end where @opaque t() :: %__MODULE__{:data => :queue.queue()}
That could well justify the issue you're seeing. What happens if instead of |
I think what @paulo-ferraz-oliveira said is possible, but I think more likely is that dialyzer doesn't see a path where Dialyzer in this sense is never wrong 😄 Edit : If you hack around you will find this is issues ranging from the skip_count to, empty lists, indexes, etc.) You can make those problems go away, but you'll end up with an entirely new dialyzer error, which is also probably not wrong. I hope this helps |
Yeah, you're most likely right, @starbelly. I got side-tracked by the fact that "Elixir wrapper" is mentioned, but now I cloned and checked the code and
provokes an issue, per Dialyzer analysis (even if no issue is actually revealed when running the code, since this might be just typing). Edit: and I also failed to see that " |
Thanks for your time @paulo-ferraz-oliveira @starbelly; while I'm certain there is no dead/unaccessible code, I can't really pinpoint the exact source of this issue either :/ You can run |
Without knowing much about Elixir, my simplistic analysis is the same as @paulo-ferraz-oliveira Apart from that, I think the entry point of A quick look tells that line 135 sets always defp serialize_track(
%Track{} = track,
target_duration,
delta_ctx \\ %{skip_count: 0, skip_duration: 0}
) do
supports_ll_hls? = Track.supports_partial_segments?(track)
so there is only one case to handle, line 138 for which Dialyzer seems to infer that |
This one continued to bug me 😄 So the problem here is non-obvious. I believe dialyzer is getting confused per opaque types and how the code ends up as erlang, specifically with map access in elixir (i.e., If you bind If we de-compile the elixir to erlang we can perhaps start to get an idea of why (sort of) :
Now, of course, that's nothing new, just how that works. I haven't seen a case like this before (or that I can remember), but it may be that the match all clause at the bottom doesn't doesn't play well with an opaque type of Qex.t/1 which in turn defines a type that is another opaque type (queue:queue/1). You could swap it out for MapSet.t(), as those should be similar in their type definitions. Likewise, you can avoid this situation by also opting out of specifying your segments key as I'd have to dig further to understand what's going on, while Qex's types are little funny (defined slightly differently from how I've seen with modules such as MapSet or queue itself), that doesn't seem to be an issue though (in general). Anyway, it's an interesting find none the less. Look forward to hearing more (if I don't dig first!) 😄 |
Thank you @starbelly, binding The "unfixed" version will be available at the tag |
Cool. A couple of call outs.
My 2 cents and hunch, which may be wrong, is this is not a problem in dialyzer. That said, purely out of interest and when I can find some type, I will see if I can reproduce the problem in erlang (unless someone gets there first). |
Thanks for all the work. Thanks everyone! |
Describe the bug
Dialyzer does not complain when code uses
Enum.reverse/1
, but when it is replaced withQex.reverse/1
(which AFAIK is an Elixir wrapper on:queue.reverse/1
), it emits several warnings seemingly unrelated to the call, such as "pattern will never match" and "guard can never succeed".To Reproduce
CAN-SKIP-UNTIL
and delta generation membraneframework/membrane_http_adaptive_stream_plugin#88)@dialyzer
tags inlib/membrane_http_adaptive_stream/hls.ex
mix deps.get
andmix dialyzer
Expected behavior
Task
mix.dialyzer
passes with no warnings emittedAffected versions
Elixir 1.15.5-otp-26
Erlang 26.0.2
Additional context
The
Qex.reverse/1
call happens in the following function (source):If
|> Qex.reverse()
is replaced with|> Enum.reverse()
, the Dialyzer warnings disappear. Interestingly, the warnings also disappear if you insert either|> IO.inspect()
or|> Function.identity()
just before|> Qex.reverse()
...The emitted warnings are:
I wasn't able to reproduce the bug in a minimal example, so the problem may be caused by interactions with something else. Apologies in advance if this turns out not to be a Dialyzer issue
The text was updated successfully, but these errors were encountered: