dialyxir icon indicating copy to clipboard operation
dialyxir copied to clipboard

CaseClauseError running with --force-check

Open mguimas opened this issue 5 years ago • 6 comments

Environment

$ elixir --version
Erlang/OTP 21 [erts-10.2.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Elixir 1.8.1 (compiled with Erlang/OTP 21)

$ cat mix.lock | grep dialyxir
  "dialyxir": {:hex, :dialyxir, "1.0.0-rc.4", "71b42f5ee1b7628f3e3a6565f4617dfb02d127a0499ab3e72750455e986df001", [:mix], [{:erlex, "~> 0.1", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm"}

Current behavior

Running with --force-check causes the following problem:

$ mix dialyzer --force-check
==> things
Compiling 2 files (.ex)
Generated things app
==> persistent
Compiling 6 files (.ex)
In an Umbrella child, not checking PLT...
Starting Dialyzer
[
  check_plt: true,
  init_plt: '/home/user/.project/_build/dev/dialyxir_erlang-21.2.5_elixir-1.8.1_deps-dev.plt',
  files_rec: ['/home/user/.project/_build/dev/lib/persistent/ebin'],
  warnings: [:unknown]
]
** (CaseClauseError) no case clause matching: {{:nocatch, {:dialyzer_error, [78, 111, 116, 32, 97, 32, 114, 101, 103, 117, 108, 97, 114, 32, 102, 105, 108, 101, 58, 32, '/home/user/.project/_build/dev/lib/things/ebin/Elixir.AAA.beam', 10]}}, [{:dialyzer_plt, :compute_md5_from_file, 1, [file: 'dialyzer_plt.erl', line: 543]}, {:dialyzer_plt, :compute_new_md5_1, 3, [file: 'dialyzer_plt.erl', line: 509]}, {:dialyzer_plt, :check_plt1, 3, [file: 'dialyzer_plt.erl', line: 479]}, {:dialyzer_plt, :"-subproc/1-fun-0-", 1, [file: 'dialyzer_plt.erl', line: 603]}]}
    dialyzer_cl.erl:249: :dialyzer_cl.check_plt/3
    dialyzer_cl.erl:182: :dialyzer_cl.plt_common/3
    dialyzer.erl:94: anonymous fn/1 in :dialyzer.cl_check_init/1
    dialyzer.erl:236: :dialyzer.doit/1
    dialyzer.erl:172: :dialyzer.check_init/1
    dialyzer.erl:159: :dialyzer.run/1
    (stdlib) timer.erl:181: :timer.tc/2
    lib/dialyxir/dialyzer.ex:39: Dialyxir.Dialyzer.Runner.run/2

Expected behavior

It should check the PLT, instead of giving this error.

mguimas avatar Mar 21 '19 19:03 mguimas

Making the error readable:

path =
  {{
    :nocatch,
    {
      :dialyzer_error,
      [78, 111, 116, 32, 97, 32, 114, 101, 103, 117, 108, 97, 114, 32, 102, 105, 108, 101, 58, 32, '/home/user/.project/_build/dev/lib/things/ebin/Elixir.AAA.beam', 10]
    }
  }, [
    {:dialyzer_plt, :compute_md5_from_file, 1, [file: 'dialyzer_plt.erl', line: 543]},
    {:dialyzer_plt, :compute_new_md5_1, 3, [file: 'dialyzer_plt.erl', line: 509]},
    {:dialyzer_plt, :check_plt1, 3, [file: 'dialyzer_plt.erl', line: 479]},
    {:dialyzer_plt, :"-subproc/1-fun-0-", 1, [file: 'dialyzer_plt.erl', line: 603]}
  ]}
  |> elem(0)
  |> elem(1)
  |> elem(1)

:io.format("~ts", [path])
$ elixir error.exs
Not a regular file: /home/user/.project/_build/dev/lib/things/ebin/Elixir.AAA.beam

evnu avatar Apr 09 '19 10:04 evnu

The error is thrown within this function in dialyzer_plt.erl:

compute_md5_from_file(File) ->
  case beam_lib:all_chunks(File) of
    {ok, _, Chunks} ->
      %% We cannot use beam_lib:md5 because it does not consider
      %% the debug_info chunk, where typespecs are likely stored.
      %% So we consider almost all chunks except the useless ones.
      Filtered = [[ID, Chunk] || {ID, Chunk} <- Chunks, ID =/= "CInf", ID =/= "Docs"],
      erlang:md5(lists:sort(Filtered));
    {error, beam_lib, {file_error, _, enoent}} ->
      Msg = io_lib:format("Not a regular file: ~ts\n", [File]),
      throw({dialyzer_error, Msg}); % <-------------------------------- Here.
    {error, beam_lib, _} ->
      Msg = io_lib:format("Could not compute MD5 for .beam: ~ts\n", [File]),
      throw({dialyzer_error, Msg})
  end.

Apparently, Elixir.AAA.beam does not exist (enoent). The full stack trace at the throw-site is possibly more useful:

[
    {:dialyzer_plt, :compute_md5_from_file, 1, [file: 'dialyzer_plt.erl', line: 543]},
    {:dialyzer_plt, :compute_new_md5_1, 3, [file: 'dialyzer_plt.erl', line: 509]},
    {:dialyzer_plt, :check_plt1, 3, [file: 'dialyzer_plt.erl', line: 479]},
    {:dialyzer_plt, :"-subproc/1-fun-0-", 1, [file: 'dialyzer_plt.erl', line: 603]}
]

evnu avatar Apr 09 '19 22:04 evnu

Thanks for investigating! I think we need to handle any {:dialyzer_error, binary()} by printing the binary as an error and then halt the VM with a non-zero.

jeremyjh avatar Apr 10 '19 11:04 jeremyjh

Thanks for investigating! I think we need to handle any {:dialyzer_error, binary()} by printing the binary as an error and then halt the VM with a non-zero.

Yes, that would make sense. I still wonder what triggered that exception in the first place. I tried to "fuzz" this behaviour by corrupting and removing a .beam file, but was not able to trigger it.

evnu avatar Apr 10 '19 11:04 evnu

I just came across this error too. I removed the /priv/plts/ and the error is gone. Leaving it here for people who might be looking for a solution.

** (CaseClauseError) no case clause matching: 
{{:nocatch,
  {:dialyzer_error,
   [
     70,
     105,
     108,
     101,
     32,
     110,
     111,
     116,
     32,
     102,
     111,
     117,
     110,
     100,
     58,
     32,
     '/opt/homebrew/Cellar/erlang/24.0.4_1/lib/erlang/lib/dialyzer-4.4.1/ebin/erl_bif_types.beam',
     10
   ]}},
 [
   {:dialyzer_plt, :compute_md5_from_file, 1, [file: 'dialyzer_plt.erl', line: 543]},
   {:dialyzer_plt, :compute_new_md5_1, 3, [file: 'dialyzer_plt.erl', line: 509]},
   {:dialyzer_plt, :check_version, 1, [file: 'dialyzer_plt.erl', line: 328]},
   {:dialyzer_plt, :check_plt1, 3, [file: 'dialyzer_plt.erl', line: 477]},
   {:dialyzer_plt, :"-subproc/1-fun-0-", 1, [file: 'dialyzer_plt.erl', line: 603]}
 ]}

felipero avatar Aug 25 '21 06:08 felipero

Don't know if this is the same issue but I get this:

{{:nocatch,
  {:dialyzer_error,
   [
     78,
     111,
     116,
     32,
     97,
     32,
     114,
     101,
     103,
     117,
     108,
     97,
     114,
     32,
     102,
     105,
     108,
     101,
     58,
     32,
     '/nix/store/0lci3ngi5cqpmcb6y0ds5ri1vf6y8jyi-erlang-22.3.4.9/lib/erlang/lib/hipe-3.19.3/ebin/erl_bif_types.beam',
     10
   ]}},
 [
   {:dialyzer_plt, :compute_md5_from_file, 1, [file: 'dialyzer_plt.erl', line: 543]},
   {:dialyzer_plt, :compute_new_md5_1, 3, [file: 'dialyzer_plt.erl', line: 509]},
   {:dialyzer_plt, :check_version, 1, [file: 'dialyzer_plt.erl', line: 328]},
   {:dialyzer_plt, :check_plt1, 3, [file: 'dialyzer_plt.erl', line: 477]},
   {:dialyzer_plt, :"-subproc/1-fun-0-", 1, [file: 'dialyzer_plt.erl', line: 603]}
 ]}
    dialyzer_cl.erl:250: :dialyzer_cl.check_plt/3
    dialyzer_cl.erl:183: :dialyzer_cl.plt_common/3
    dialyzer.erl:160: :dialyzer.run/1
    lib/dialyxir/plt.ex:219: Dialyxir.Plt.plt_run/1
    lib/dialyxir/plt.ex:199: Dialyxir.Plt.plt_remove/2
    lib/dialyxir/plt.ex:145: Dialyxir.Plt.check_beams/3
    lib/dialyxir/plt.ex:44: Dialyxir.Plt.check_plt/4
    (elixir 1.10.4) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
    lib/mix/tasks/dialyzer.ex:250: Mix.Tasks.Dialyzer.check_plt/1
    lib/mix/tasks/dialyzer.ex:170: Mix.Tasks.Dialyzer.run/1
    (mix 1.10.4) lib/mix/task.ex:330: Mix.Task.run_task/3
    (mix 1.10.4) lib/mix/cli.ex:82: Mix.CLI.run_task/2
    (elixir 1.10.4) lib/code.ex:926: Code.require_file/2

Deleting all plts folders (as @felipero) suggested didn't fix it for me. I've also tried deleting the _build and deps folders but even that doesn't help.

EDIT:

Oh, the fix from #335 (delete old plt files) worked for me.

jtrees avatar Sep 02 '21 09:09 jtrees