W0020 - Unused Include
Error
//- /include/foo.hrl
-define(FOO,3).
//- /src/foo.erl
-module(foo).
-include("foo.hrl").
%%^^^^^^^^^^^^^^^^^^^^ 💡 warning: Unused file: foo.hrl
Explanation
The warning message indicates that no definitions or attributes contained in the foo.hrl header are used in the foo module and therefore the include statement can be safely removed from foo.erl.
A header is judged by what it contributes where it is included, rather than by what it contains when read on its own. Conditional sections are evaluated against the macros in scope at that point, so a header wrapped in the usual include guard contributes nothing once it has already been included earlier in the same module, whether directly or through another header:
//- /include/guarded.hrl
-ifndef(GUARDED_HRL).
-define(GUARDED_HRL, true).
-record(rec, {field}).
-endif.
//- /include/outer.hrl
-include("guarded.hrl").
//- /src/foo.erl
-module(foo).
-include("guarded.hrl").
-include("outer.hrl").
%%^^^^^^^^^^^^^^^^^^^^^^ 💡 warning: Unused file: outer.hrl
foo(X) -> X#rec.field.
An explicitly named header is also treated as a direct dependency when another direct header includes the same file transitively. W0020 attributes the module's actual resolved definitions to the files that declared them, so an include guard tripped by the transitive copy does not cause the direct include to be reported. Definitions declared by that header count only for its direct include, not for another direct header that happens to include it transitively. This keeps modules from depending accidentally on another header's implementation details.
In case of a false positive, please use the standard elp:ignore mechanism to temporarily silence the warning and report this as a bug.