Elixir and Erlang/OTP versions
Erlang/OTP 27 [erts-15.2.7.6] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
Elixir 1.19.5 (compiled with Erlang/OTP 27)
Operating system
Fedora Linux 42 with Nix
Current behavior
I hit this corner case in our repo after upgrading to Elixir 1.19. I was able to reduce it to a very small repro.
The issue appears only when debug info is disabled. With --no-debug-info (in our case it was elixirc_options: [debug_info: ...]), incremental compilation can emit a false undefined warning for a module/function that exists.
I am attaching incremental_warning_repro.patch, which creates the complete minimal Mix project. The key modules are:
lib/source.ex
defmodule IncrementalWarningRepro.Source do
# REPRO_EDIT: 1
def identity(value), do: value
end
lib/dependent.ex
defmodule IncrementalWarningRepro.Dependent do
def touch_source, do: IncrementalWarningRepro.Source.identity(:ok)
def run, do: :ok
end
lib/caller.ex
defmodule IncrementalWarningRepro.Caller do
@compile_time_value IncrementalWarningRepro.Source.identity(:ok)
def compile_time_value, do: @compile_time_value
def call_dependent, do: IncrementalWarningRepro.Dependent.run()
end
Reproducing steps:
# apply the attached patch to create the minimal repro project
git apply incremental_warning_repro.patch
cd incremental_warning_repro
# baseline compile with debug info disabled; this is clean
mix compile --no-debug-info
# change only a comment to trigger incremental recompilation
sed -i 's/# REPRO_EDIT: 1/# REPRO_EDIT: 2/' lib/source.ex
# compile again with debug info still disabled; this prints the warning
mix compile --no-debug-info
The second compile prints:
$ mix compile --no-debug-info
Compiling 2 files (.ex)
warning: IncrementalWarningRepro.Dependent.run/0 is undefined (module IncrementalWarningRepro.Dependent is not available or is yet to be defined). Did you mean:
* IncrementalWarningRepro.Dependent.run/0
│
5 │ def call_dependent, do: IncrementalWarningRepro.Dependent.run()
│ ~
│
└─ lib/caller.ex:5:61: IncrementalWarningRepro.Caller.call_dependent/0
Generated incremental_warning_repro app
The dependency shape in the repro is:
Caller -> Source at compile time via a module attribute
Dependent -> Source at runtime
Caller -> Dependent at runtime
Changing Source recompiles Caller, does not recompile Dependent, and then the verifier warns that Dependent.run/0 is undefined even though Dependent exists.
Additional context:
- With debug info enabled, the warning disappears.
mix compile --no-debug-info --no-verification is clean.
Possible cause:
Elixir 1.19's incremental verification appears to reconstruct already-compiled dependent modules from BEAM metadata more often. When those modules were compiled with debug_info: false, Module.ParallelChecker seems to treat the dependent module as unavailable instead of falling back to an export-only check, which then surfaces as a false undefined warning in the recompiled caller.
Expected behavior
No undefined warning should be emitted here. The module and function exist, and incremental verification should either succeed or degrade gracefully when compiling with --no-debug-info.
Elixir and Erlang/OTP versions
Operating system
Fedora Linux 42 with Nix
Current behavior
I hit this corner case in our repo after upgrading to Elixir 1.19. I was able to reduce it to a very small repro.
The issue appears only when debug info is disabled. With
--no-debug-info(in our case it waselixirc_options: [debug_info: ...]), incremental compilation can emit a false undefined warning for a module/function that exists.I am attaching
incremental_warning_repro.patch, which creates the complete minimal Mix project. The key modules are:lib/source.exlib/dependent.exlib/caller.exReproducing steps:
The second compile prints:
The dependency shape in the repro is:
Caller -> Sourceat compile time via a module attributeDependent -> Sourceat runtimeCaller -> Dependentat runtimeChanging
SourcerecompilesCaller, does not recompileDependent, and then the verifier warns thatDependent.run/0is undefined even thoughDependentexists.Additional context:
mix compile --no-debug-info --no-verificationis clean.Possible cause:
Elixir 1.19's incremental verification appears to reconstruct already-compiled dependent modules from BEAM metadata more often. When those modules were compiled with
debug_info: false,Module.ParallelCheckerseems to treat the dependent module as unavailable instead of falling back to an export-only check, which then surfaces as a false undefined warning in the recompiled caller.Expected behavior
No undefined warning should be emitted here. The module and function exist, and incremental verification should either succeed or degrade gracefully when compiling with
--no-debug-info.