jeremyjh / dialyxir

Mix tasks to simplify use of Dialyzer in Elixir projects.
Apache License 2.0
1.68k stars 142 forks source link

Elixir 1.15 + Umbrella Project + Dialyzer issues #508

Open elliottneilclark opened 1 year ago

elliottneilclark commented 1 year ago

Environment

Elixir 1.15.0 (compiled with Erlang/OTP 25)

Current behavior

I have an umbrella project with Phoenix + LiveView that worked well on 1.14 and is broken in 1.15. To reproduce it's pretty easy:

Looking up modules in dialyxir_erlang-25.3.2.2_elixir-1.15.0_deps-dev.plt
** (UndefinedFunctionError) function :dialyzer_plt.included_files/1 is undefined (module :dialyzer_plt is not available)
    (dialyzer 5.0.5) :dialyzer_plt.included_files(~c"/home/elliott/Code/dialyzer_new_umbrella/_build/dev/dialyxir_erlang-25.3.2.2_elixir-1.15.0_deps-dev.plt")
    (dialyzer 5.0.5) dialyzer.erl:228: :dialyzer.plt_info/1
    (dialyxir 1.3.0) lib/dialyxir/plt.ex:243: Dialyxir.Plt.plt_files/1
    (dialyxir 1.3.0) lib/dialyxir/plt.ex:16: Dialyxir.Plt.find_plts/3
    (dialyxir 1.3.0) lib/mix/tasks/dialyzer.ex:254: Mix.Tasks.Dialyzer.check_plt/1
    (dialyxir 1.3.0) lib/mix/tasks/dialyzer.ex:174: Mix.Tasks.Dialyzer.run/1
    (mix 1.15.0) lib/mix/task.ex:447: anonymous fn/3 in Mix.Task.run_task/5
    (mix 1.15.0) lib/mix/cli.ex:92: Mix.CLI.run_task/2

This worked with 1.14. I've put together an example repo: https://github.com/elliottneilclark/dialyzer_new_umbrella that will fail with 1.15.0 and work with the latest 1.14. If you already use nix it should be set up to reproduce. https://github.com/elliottneilclark/dialyzer_new_umbrella/blob/830f9c867a1938af97e6e56357fe7d19f2a6b04b/flake.nix#L38 You can change that line to see it work in 1.14

If I add dialyxir as a dependency to each sub-app, it seems to work, however, it complains LOUDLY about missing deps.

Expected behavior

I would expect to be able to upgrade from 1.14 to 1.15 successfully.

https://gist.github.com/elliottneilclark/33cb21c37be951a38268217a8a2e1f1c

carlogilmar commented 1 year ago

Yeah, I was looking into this error that we had first in the GitHub Action after upgrade our application. 🥴

I'm using Elixir 1.15.0 (OTP 26) installed by ASDF.

image

carlogilmar commented 1 year ago

Reading about the new elixir release, mention this:

image

After set this in my mix.exs I was able to run dialyzer in my local and in the CI. Although I got this errors:

image

elliottneilclark commented 1 year ago

I prefer keeping that setting safer. I did find that adding:

{:dialyxir, "~> 1.3", only: [:dev, :test], runtime: false},

into every sub-application worked around everything. See this example commit: https://github.com/elliottneilclark/dialyzer_new_umbrella/commit/aaba7c648ed6de065d424b751526c21ea9873f6a I'm not sure why credo can work when added to the umbrella, but dialyzer fails.

jeremyjh commented 1 year ago

Dialyxir has a runtime dependency on :dialyzer and the dialyxir strategy for umbrella apps is actually to dialyze each application separately, so we have to be sure :dialyzer is included in extra_applications for each child in some way. I'd prefer to address this by changing this design, it would address several other issues. https://github.com/jeremyjh/dialyxir/issues?q=is%3Aissue+is%3Aopen+umbrella

denvaar commented 1 year ago

@elliottneilclark Adding to each umbrella app seems to fix the UndefinedFunctionError error, but I still get this big list of "dependency list may be incomplete". Is that what you're seeing as well?

elliottneilclark commented 1 year ago

@denvaar Yep that's what I see as well. I think the warnings are from #502

carlogilmar commented 1 year ago

Curious, after add dialyzer as dep in every umbrella app I got same errors

image

Toady00 commented 1 year ago

I came here having a similar problem with elixir 1.15.2 and erlang 26.0.2. After reading this issue I tried adding {:dialyxir, "~> 1.3", only: [:dev, :test], runtime: false} to each sub app and that appears to have solved the issue. My error was different though, and I figured I'd share it here in case it's helpful. When I run mix dialyzer from the umbrella root I got this odd error:

$ mix dialyzer
** (UndefinedFunctionError) function Dialyxir.Output.info/1 is undefined (module Dialyxir.Output is not available)
    (dialyxir 1.3.0) Dialyxir.Output.info("Finding suitable PLTs")
    (dialyxir 1.3.0) lib/mix/tasks/dialyzer.ex:172: Mix.Tasks.Dialyzer.run/1
    (mix 1.15.2) lib/mix/task.ex:447: anonymous fn/3 in Mix.Task.run_task/5
    (mix 1.15.2) lib/mix/cli.ex:92: Mix.CLI.run_task/2
Error: exit status 1
carlogilmar commented 1 year ago

@Toady00 Did you try adding prune_code_paths: false in your mix.exs? For me, dialyzer works, but have a looooot of warnings and errors

Toady00 commented 1 year ago

@carlogilmar I didn't want to disable that functionality if I could help it so no, I didn't add that. But it works as expected adding it to every child's mix.exs

thbar commented 10 months ago

After reading this issue I tried adding {:dialyxir, "~> 1.3", only: [:dev, :test], runtime: false} to each sub app and that appears to have solved the issue

Came to comment this also solved the issue for us (umbrella app). Thanks!

timothyvanderaerden commented 10 months ago

This seems to be fixed with Elixir 1.15.6, the workaround is not needed anymore for umbrella projects.

lukaszsamson commented 9 months ago

I'm seeing the same

Unknown application :debugger
Unknown application :hex

when running dialyxir on ElixirLS repo. Those apps are explicitly listed in plt_add_apps