dialyxir
dialyxir copied to clipboard
Ignore_warnings file not ignoring warnings after upgrade to OTP 24
Precheck
-
[x] Take a look at the open issues and be sure that your issue is not already covered:
Related, but not same: https://github.com/jeremyjh/dialyxir/issues/435
-
[x] Be sure your versions of Dialyxir and Erlex are up to date.
Environment
- Elixir & Erlang/OTP versions (elixir --version):
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
Elixir 1.12.3 (compiled with Erlang/OTP 24)
- Which version of Dialyxir are you using? (cat mix.lock | grep dialyxir):
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
Current behavior
TLDR: Warnings are emitted even after placing filters in the ignore file.
While working in another big project, we silenced an Dialyzer warning (due to the use of money ecto type) through the use of the ignore_warnings file.
After updating to OTP 24, the warnings showed up again when running mix dialyzer
, this is preventing us from updating to OTP 24, since it's failing at our CI.
This repo attempts to provide a reproducible example of the warning through a wrong spec, although it's not the only warning we're getting (and in a different scenario).
Dialyzer output:
❯ mix dialyzer
Finding suitable PLTs
Checking PLT...
[:compiler, :elixir, :kernel, :logger, :money, :stdlib]
PLT is up to date!
ignore_warnings: .dialyzer_ignore.exs
Starting Dialyzer
[
check_plt: false,
init_plt: '.../dialyxir_test/_build/dev/dialyxir_erlang-24.0.2_elixir-1.12.3_deps-dev.plt',
files: [...],
warnings: [:unknown]
]
Total errors: 1, Skipped: 0, Unnecessary Skips: 1
done in 0m1.19s
lib/dialyxir_test.ex:19:unknown_type
Unknown type: Money.Ecto.Composite.Type.t/0.
________________________________________________________________________________
done (warnings were emitted)
Halting VM with exit status 2
ignore file (we use line 19 for this example, but the actual error is on line 0):
# This file should be empty ALWAYS. Use it only for emergencies.
[
{":19:unknown_type Unknown type: Money.Ecto.Composite.Type.t/0."},
]
mix file:
defmodule DialyxirTest.MixProject do
use Mix.Project
def project do
[
app: :dialyxir_test,
version: "0.1.0",
elixir: "~> 1.12",
start_permanent: Mix.env() == :prod,
deps: deps(),
dialyzer: [
ignore_warnings: ".dialyzer_ignore.exs",
]
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:money, "~> 1.9.0"},
{:dialyxir, "~> 1.0", only: [:dev], runtime: false},
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end
Expected behavior
It should ignore the warnings specified in the ignore file.
I forked the project since I too have this issue when using dialyxir
on Elixir 1.13 and OTP24. On my fork I tried different combinations of Elixir/OTP pairings whilst running the CI steps of this project under GitHub actions. The results I got were that the builds fail when the library switches to 1.13
and this is the specific log of the job for Elixir 1.13 / OTP 22.3
mix dialyzer --format short
shell: /usr/bin/bash -e {0}
env:
INSTALL_DIR_FOR_OTP: /home/runner/work/_temp/.setup-beam/otp
INSTALL_DIR_FOR_ELIXIR: /home/runner/work/_temp/.setup-beam/elixir
MIX_ENV: prod
Finding suitable PLTs
Checking PLT...
[:dialyzer, :elixir, :erlex, :kernel, :mix, :stdlib]
Looking up modules in dialyxir_erlang-22.[3](https://github.com/octowombat/dialyxir/runs/5456638012?check_suite_focus=true#step:11:3).[4](https://github.com/octowombat/dialyxir/runs/5456638012?check_suite_focus=true#step:11:4).24_elixir-1.13.3_deps-prod.plt
Looking up modules in dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Looking up modules in dialyxir_erlang-22.3.4.24.plt
Finding applications for dialyxir_erlang-22.3.4.24.plt
Finding modules for dialyxir_erlang-22.3.4.24.plt
Creating dialyxir_erlang-22.3.4.24.plt
Looking up modules in dialyxir_erlang-22.3.4.24.plt
Removing 3 modules from dialyxir_erlang-22.3.4.24.plt
Checking 18 modules in dialyxir_erlang-22.3.4.24.plt
Adding 176 modules to dialyxir_erlang-22.3.4.24.plt
done in 1m2.66s
Finding applications for dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Finding modules for dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Copying dialyxir_erlang-22.3.4.24.plt to dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Looking up modules in dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Checking 194 modules in dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
Adding 247 modules to dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt
done in 0m41.48s
Finding applications for dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
Finding modules for dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
Copying dialyxir_erlang-22.3.4.24_elixir-1.13.3.plt to dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
Looking up modules in dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
Checking 441 modules in dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
Adding 121 modules to dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt
done in 0m22.48s
ignore_warnings: .dialyzer_ignore.exs
Starting Dialyzer
[
check_plt: false,
init_plt: '/home/runner/work/dialyxir/dialyxir/_build/prod/dialyxir_erlang-22.3.4.24_elixir-1.13.3_deps-prod.plt',
files: ['/home/runner/work/dialyxir/dialyxir/_build/prod/lib/dialyxir/ebin/Elixir.Dialyxir.Project.beam',
'/home/runner/work/dialyxir/dialyxir/_build/prod/lib/dialyxir/ebin/Elixir.Dialyxir.Warnings.OverlappingContract.beam',
'/home/runner/work/dialyxir/dialyxir/_build/prod/lib/dialyxir/ebin/Elixir.Dialyxir.Warnings.FunctionApplicationNoFunction.beam',
'/home/runner/work/dialyxir/dialyxir/_build/prod/lib/dialyxir/ebin/Elixir.Dialyxir.WarningHelpers.beam',
'/home/runner/work/dialyxir/dialyxir/_build/prod/lib/dialyxir/ebin/Elixir.Mix.Tasks.Dialyzer.Explain.beam',
...],
warnings: [:unmatched_returns, :error_handling, :underspecs, :unknown]
]
Total errors: 3, Skipped: 2, Unnecessary Skips: 0
done in 0m1.38s
lib/dialyxir/project.ex:4[5](https://github.com/octowombat/dialyxir/runs/5456638012?check_suite_focus=true#step:11:5):unmatched_return The expression produces multiple types, but none are matched.
done (warnings were emitted)
Halting VM with exit status 2
Error: Process completed with exit code 2.
I am going to therefore investigate from the release of 1.13 and the command mix dialyzer --format short
.
From what I have found so far using a fork from this repo and no other changes, just using asdf
to install local matrix of OTP and Elixir releases is that when I run mix dialyzer --format short
(sticking with OTP 24.2) ;
- For Elixir 1.12.3 it produces no warnings on the project at all, notably not the above
:unmatched_returns
warning and thus the.dialyzer_ignore.exs
file is not brought into play. - From Elixir 1.13.0 through to 1.13.2 it produces the warning (in red)
lib/dialyxir/project.ex:45:unmatched_return The expression produces multiple types, but none are matched.
- If I add the short form or warning as a term into the
.dialyzer_ignore.exs
verbatim, namely add a line thus{"lib/dialyxir/project.ex:45:unmatched_return The expression produces multiple types, but none are matched."}
and re-runmix dialyzer --format short
the warning file is honoured and no warning appears. - If I replace this line by the alternative of
{"lib/dialyxir/project.ex", :unmatched_return}
it equally returns no warnings and the warning file is honoured once again as does adding the line number,{"lib/dialyxir/project.ex", :unmatched_return, 45}
. -
HOWEVER, if I try to use the shorthand version hinted at in the documentation (which I have to confess I usually always do),
{":0:unmatched_return The expression produces multiple types, but none are matched."}
, then runningmix dialyzer --format short
does produce the red warning.
So the question is, in point 1 above, why in the case of this project (dog-fooding itself!) does the warning not appear until Elixir 1.13.x?
The dialyzer
block in the mix.exs
file has the following:
dialyzer: [
plt_apps: [:dialyzer, :elixir, :kernel, :mix, :stdlib, :erlex],
ignore_warnings: ".dialyzer_ignore.exs",
flags: [:unmatched_returns, :error_handling, :underspecs]
]
which I thought would produce the warning from specifying the flag
(in this case :unmatched_returns
). Quoting from the Erlang manual:
-Wunmatched_returns (***) Include warnings for function calls that ignore a structured return value or do not match against one of many possible return values. However, no warnings are included if the possible return values are a union of atoms or a union of numbers. *** denotes options that turn on warnings rather than turning them off.
Let's look more closely then at this case of Project.ex:45
. The line in question is as follows
Mix.Tasks.Deps.Loadpaths.run([])
When we use Elixir 1.13.x, this produces a list of paths to dependencies such as
["/Volumes/Development/projects/dialyxir/_build/dev/lib/earmark_parser/ebin",
"/Volumes/Development/projects/dialyxir/_build/dev/lib/erlex/ebin",
"/Volumes/Development/projects/dialyxir/_build/dev/lib/nimble_parsec/ebin",
"/Volumes/Development/projects/dialyxir/_build/dev/lib/makeup/ebin",
"/Volumes/Development/projects/dialyxir/_build/dev/lib/makeup_elixir/ebin",
"/Volumes/Development/projects/dialyxir/_build/dev/lib/ex_doc/ebin"]
BUT when using Elixir 1.12.3 (for example), it produces simply :ok
which means it must have only atom return values according to the above Erlang docs so as not to produce the dialyzer warning in this case. This change came about in Elixir 1.13 from my reading of the git blame results.
So for the dog-food example of dialyxir
itself, this change exposes a warning that wasn't exposed previously and as such the CI on this project will fail unless we add the correct form of warning into the ignore file (assuming of course we want to ignore the warning). And for the rest of us, the changes to Elixir 1.13 may also expose new warnings and if we want to ignore them now, we can use mix dialyzer --format short
or mix dialyzer --format ignore_file
and grab the correct form of entry to add to our .dialyzer_ignore.exs
files.
I hope this helps!
Any progress on this one? For me my dialyzer is acting up with ExUnit when running in MIX_ENV=test
.
For now I can find an entry for my ignore dotfile via mix dialyzer --format ignore_file
but they basically just ignore a quite generic error {"test/support/data_case.ex", :unknown_function}
. Tested on OTP25
with 1.13.2
and 1.14
.
Does this change fix it for you? https://github.com/jeremyjh/dialyxir/issues/444#issuecomment-940223772
If so, I have a fork with the change implemented here: https://github.com/connorjacobsen/dialyxir/commit/499b54b4872ca396002ec517e46c8d602c1e113d
This doesn't seem to be an issue for me using:
❯ cat .tool-versions
elixir 1.14.1-otp-25
erlang 25.1.1
We have Dialyxir running in CI using an ignore file and everything works as expected. 🤔
@nezteb It looks like it may be an issue with ignore files using --format dialyzer
in a dialyzer.ignore-warnings
file ? But not in the term format in an exs file.