$ asdf current
elixir 1.9.2-otp-22 (set by …)
erlang 22.1.5 (set by …)
$ elixir -v
Erlang/OTP 22 [erts-10.5.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Elixir 1.9.2 (compiled with Erlang/OTP 22)
I'm using latest openSUSE Tumbleweed for x64 CPU with KDE/Plasma 5 desktop.
Hi, today I found something really weird. In __using__/1 macro I was generating module String. Of course such name is not good and instead of MyLib.String there should be for example MyLib.StringUtils, but name was only temporary.
In such generated module I placed function/macro (does not matter), added docs and typespecs. That macro was really short, so I immediately started to work on another part without compiling it. Later I noticed really weird error:
Compiling 1 file (.ex)
Cover compiling modules ...
** (exit) an exception was raised:
** (MatchError) no match of right hand side value: :error
cover.erl:1605: :cover.do_compile_beam2/6
cover.erl:1497: :cover.do_compile_beam/3
(stdlib) lists.erl:1239: :lists.map/2
cover.erl:2925: anonymous fn/2 in :cover.pmap_spawn/4
cover.erl:602: :cover.call/1
(mix) lib/mix/tasks/test.ex:12: Mix.Tasks.Test.Cover.start/2
(mix) lib/mix/tasks/test.ex:407: Mix.Tasks.Test.do_run/3
(mix) lib/mix/task.ex:331: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
This does not give me any hint, so I was confused for a longer time. Without any idea what's happening I decided for desperate move i.e. comment all of my code part by part and see if something has changed and that's how I found it. :smile:
Here is an example code:
defmodule MyLib.String do
defmacro __using__(_opts \\ []) do
quote unquote: false do
defmodule String do
@spec example() :: String.t()
def example, do: "sample"
end
end
end
end
defmodule Example do
use MyLib.String
end
Of course that was mainly my bad. I don't know what I expected with such way too simple naming, but the problem was that I had no idea why I got this error.
Here is something interesting:
defmodule MyLib.String do
defmacro __using__(_opts \\ []) do
quote unquote: false do
defmodule Elixir.Example.String do
@spec example() :: String.t()
def example, do: "sample"
end
end
end
end
defmodule Example do
use MyLib.String
end
as it would not raise …
The most weird part is that it actually compiles without any warning and this error I can see only in mix test --cover task.
I'm not sure if it's a bug in typespecs handling, but in normal case no module have auto-alias in its body. If that's not a bug and it was something like using reserved word then maybe it would be possible to handle it or provide a better error message, because other people may be really confused seeing something like that.
Can you please follow the format asked in the issues template for bug reports? And don't forget to include Elixir and Erlang/OTP versions, thanks.
Right, sorry I forgot about it.
In my case if not said then you can assume latest. :smiley:
$ asdf current
elixir 1.9.2-otp-22 (set by …)
erlang 22.1.5 (set by …)
@josevalim I have updated my issue. Yesterday I was tired and just created this task fast.
The name of the module generated in this case is Example.String, not String. So there is something else here.
OK, I found the bug. Here is the root cause:
== Compilation error in file lib/foo.ex ==
** (CompileError) lib/foo.ex:13: type t/0 undefined (no such type in Example.String)
@josevalim How did you found it? In my case I do not have any compilation errors, so I'm really curious about it …
I opened cover source and found out that the line was failing was compile:forms(...). This means the Erlang AST we emitted was invalid.
I rewrote the code to Erlang and found the root cause
I added the missing verification the Erlang pass had and we didn't
I know this is a long dead issue, but I figure it wouldn't hurt to ask here.
Do you think that adding the module that is being compiled (and failed) to the :cover.do_compile_beam2/6 error would be a experience improvement? Or is there something I'm missing and it wouldn't be a good idea? It seems like a potential good first commit to BEAM for me if it's a good idea.
I just spent ~2 hours tracking down this same error, and it ended up being a dialyzer module attribute ignoring a function that didn't exist (copy/paste and forgot to rename it). Like @dialyzer {:nowarn_function, execute: 2}
@sb8244 right, they would most likely accept a PR that made it clearer. However, in this case, it is also an Elixir bug, so I filed a separate report too. Thanks!
Most helpful comment
I opened cover source and found out that the line was failing was compile:forms(...). This means the Erlang AST we emitted was invalid.
I rewrote the code to Erlang and found the root cause
I added the missing verification the Erlang pass had and we didn't