Skip to content
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

Ignore_warnings file not ignoring warnings after upgrade to OTP 24 #448

Open
2 tasks done
imricardoramos opened this issue Nov 23, 2021 · 6 comments
Open
2 tasks done

Comments

@imricardoramos
Copy link

imricardoramos commented Nov 23, 2021

Precheck

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.

@octowombat
Copy link

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
image

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.

@octowombat
Copy link

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) ;

  1. 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.
  2. 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.
  3. 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-run mix dialyzer --format short the warning file is honoured and no warning appears.
  4. 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}.
  5. 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 running mix 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!

@dennym
Copy link

dennym commented Sep 27, 2022

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.

@connorjacobsen
Copy link

Does this change fix it for you? #444 (comment)

If so, I have a fork with the change implemented here: connorjacobsen@499b54b

@Nezteb
Copy link
Contributor

Nezteb commented May 3, 2023

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. 🤔

@jeremyjh
Copy link
Owner

jeremyjh commented May 3, 2023

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants