Dialyzer complains about deletion functions
icehaunter opened this issue · comments
When using (some) functions which rely on the magic :delete_me
atom, Dialyzer complains about a pattern that can never match the type (this error is for the most generic case where no types can be inferred at the place of use):
The pattern
'delete_me' can never match the type
'error' | {'ok', [any()] | tuple() | map()}
Affected functions (for me) are delete/2
, delete!/2
, and pop!/1
. pop/1
Isn't affected, and I'm not sure why.
Reproduction:
Paste this module into any project which has pathex dependency installed, and run Dialyzer.
defmodule PathexTest do
use Pathex
def pop_key_from_my_map(%{} = my_map, key) do
Pathex.delete(my_map, path(key)) # The pattern 'delete_me' can never match the type 'error' | {'ok',map()}
Pathex.delete!(my_map, path(key)) # The pattern 'delete_me' can never match the type 'error' | {'ok',map()}
Pathex.pop!(my_map, path(key)) # The pattern 'delete_me' can never match the type 'error' | {'ok',map()}
Pathex.pop(my_map, path(key)) # No warning for some reason?
end
end
For me this is reproducable on a mix new
project with two dependencies, but also causes a warning in VSCode even without the dialyxir
dependency:
[
{:pathex, "~> 2.4.2"},
{:dialyxir, "~> 1.0", only: [:dev], runtime: false}
]
My environment:
> elixir --version
Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
Elixir 1.14.1 (compiled with Erlang/OTP 25)
Yeah, this warning is true, because Pathex
generates clauses which handle {:ok, result} | :error | :delete_me
type, but paths created with path/2
macro return only {:ok, result} | :error
type.
However, this warning can't be disabled in pathex, because path
and delete
are macro, thus they're expanded at compile-time and the dialyzer won't be capable to find that this warning is disabled
You can use this regex in .dialyzer_ignore.exs
to disable the warning
~r/.*pattern_match The pattern can never match the type :error | {:ok, .*}/
Thanks for the explanation. Shame it can't be solved at the library level. mix dialyzer
does respect the suggested disable file, while ElixirLS, unfortunately, does not.
As I understand your suggestion I can disable the check, but that will be disabled for the entire codebase. Is there a possibility of fixing this problem?
Best I could do is: @dialyzer {:no_match, modify_channel_configuration_aliases: 4}
to ignore the function that calls this Library.
@grant-zukowski-xumo , the root of the problem is that dialyzer ignores generated: true
metadata in AST and still generates warnings. And there is no way to not generate the unused clause, because pathex uses code-generation to achieve performance but language has no capability for Pathex to perform the check if this clause needed or not at compile-time
Yes, you can disable checks per-function, you should use this option