W0077 - Unused Exported Function
Error
-module(main).
-export([foo/0]).
foo() -> ok.
%% ^^^ warning: W0077: Exported function foo/0 is not used anywhere else in the codebase.
Explanation
The warning indicates that the function foo/0 is exported from its module but
is never called from any other module in the codebase. Exported functions that
have no external callers represent dead code — they increase maintenance burden,
confusion, and surface area without adding value.
To fix this warning, you can either:
- Remove the export if the function is only used locally within the module
(move it from the
-exportlist and keep it as a local function). - Remove the function entirely if it is no longer needed.
- Add a caller if the function is intended to be part of the module's public API but was never integrated.
ELP provides a quick-fix that removes the function definition, its -spec, its
-doc attribute, and the entry in the -export list in a single action.
How the Linter Works
The linter iterates over every exported function in a module (including functions
exposed via -compile([export_all])) and uses ELP's
usage search to check whether any external reference
exists.
Excluded Functions
A function is skipped (never reported as unused) if any of the following apply:
| Exclusion rule | Reason |
|---|---|
module_info/0 or module_info/1 | Auto-generated by the compiler for every module. |
start_link/N | OTP convention — typically called by a supervisor tree that may not be statically visible. |
| Behaviour callbacks | The function matches a -callback declared by a behaviour the module implements (resolved via -behaviour attributes). |
All functions in Common Test suites (*_SUITE) | Common Test suites produce a high number of false positives (e.g. test functions are invoked by test runners), so they are excluded from the analysis. Test helpers that do not end in _SUITE are still analysed. |
Search Strategy
For each candidate function, two searches are performed (cheapest first):
-
Same-file search — Because the function is exported, the
-exportattribute itself counts as one reference and a-spec(if present) adds another. Any reference beyond that baseline is a real local call site, and the function is considered used. -
Project-wide search — If no local call site was found, a search is performed across every source file in the same project, excluding the defining file. If at least one external reference is found the function is considered used; otherwise a warning is emitted.
See Find References for details on how the usage search works, what counts as a reference, recognised dynamic call patterns, and general limitations.