Description
Elixir and Erlang/OTP versions
Erlang/OTP 27 [erts-15.2.7] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
Elixir 1.18.3 (compiled with Erlang/OTP 27)
Operating system
linux (but this is a compiler issue)
Current behavior
a.ex:
defmodule A do
defmacro __using__(_), do: :ok
def fun(%B{}), do: :ok
end
b.ex:
defmodule B do
use A
defstruct []
end
Causes a cylic dependency error. Error message:
== Compilation error in file lib/b.ex ==
** (CompileError) deadlocked waiting on module A
(elixir 1.18.3) src/elixir_dispatch.erl:261: :elixir_dispatch.expand_quoted/7
== Compilation error in file lib/a.ex ==
** (CompileError) deadlocked waiting on struct B
Compilation failed because of a deadlock between files.
The following files depended on the following modules:
lib/b.ex => A
lib/a.ex => B
Ensure there are no compile-time dependencies between those files and that the modules they reference exist and are correctly named
if the matching is done inside of the function body, this can be used as an escape hatch to avoid struct field type checking:
defmacrop struct_of(module, fields \\ []) do
fields = [__struct__: module | fields]
quote do
%{unquote_splicing(fields)}
end
end
but this does not work for function header matching, of course it could be in a separate module and with a require statement it works.
Expected behavior
suggested improvements:
option 1: Add "avoids type checking macro" to the kernel.
option 2: memoize all struct patterns across compiled files and defer struct field checking till a later stage in the compiler pipeline.
option 3: improve the error message to declare the nature of the cyclic dependency and provide suggestions to fix