This file provides guidance to Open Code / Codex / Claude Code (claude.ai/code) when working with code in this repository.
Infer is a multi-language static analysis tool developed by Meta. It detects bugs in Java, C, C++, Objective-C, Erlang, Hack, Python, Rust, Swift, and C# code. The primary implementation language is OCaml.
All build commands run from the repository root. You must have run ./build-infer.sh and make devsetup initially.
| Command | Purpose |
|---|---|
make -j |
Full native build (default dev mode, warnings are fatal) |
make -j BUILD_MODE=dev-noerror |
Build ignoring warnings |
make -j -C infer/src check |
Type-check only (fastest iteration cycle, requires prior full build) |
make -j -C infer/src byte |
Bytecode build (for testing changes quickly) |
make opt |
Optimized build with flambda |
make fmt |
Format changed OCaml files with ocamlformat |
make fmt_all |
Format all OCaml files |
| Command | Purpose |
|---|---|
make -j 4 test |
Run all tests (adjust parallelism to your cores) |
make -j test_build |
Verify build has no warnings |
make test-replace |
Update expected test outputs after intentional changes |
make direct_{lang}_{analyzer}_test |
Run a single test suite (rebuilds infer first) |
make -C infer/tests/codetoanalyze/{lang}/{analyzer}/ test |
Run a single test suite (assumes infer is up-to-date) |
make ocaml_unit_test |
Run OCaml unit tests only |
make swift_tests |
Run Swift tests (separate from main test target) |
Direct test names follow the pattern {lang}_{analyzer}, e.g., direct_java_pulse_test, direct_cpp_pulse_test, direct_c_frontend_test. These are defined in the DIRECT_TESTS variable in the root Makefile.
Tests live in infer/tests/codetoanalyze/{language}/{analyzer}/. Each test directory has:
- Source files to analyze
issues.expwith expected output (one issue per line)Makefilethat runs infer and diffs output againstissues.exp
Test procedure naming conventions:
*Bad— should report an error*Ok— should not report an errorFP_*— false positive (known limitation, include explanatory comment)FN_*— false negative (known limitation, include explanatory comment)
infer --debug -- clang -c examples/hello.c
firefox infer-out/captured/hello.c.*.htmlEach supported language has a frontend that translates source code into SIL (Separation Logic Intermediate Language), defined in infer/src/IR/:
| Directory | Language | Mechanism |
|---|---|---|
clang/ |
C/C++/Objective-C | Custom clang plugin (facebook-clang-plugins/) |
java/ |
Java | javalib/Sawja bytecode parsing |
erlang/ |
Erlang | Erlang compiler integration |
python/ |
Python | PyML-based frontend |
rust/ |
Rust | Charon IR translation |
llvm/ |
LLVM bitcode | LLVM OCaml bindings (used by Swift) |
textual/ |
Textual SIL | Text-based SIL representation (Hack, Python, LLVM) |
Core types: Sil.ml (instructions), Procdesc.ml (procedure descriptors), Typ.ml (types), Procname.ml (procedure names), Tenv.ml (type environments).
- Pulse (
pulse/, ~150+ files) — The main abstract domain. Handles memory safety, taint tracking, null safety, resource leaks via abductive reasoning. - Abstract interpretation framework (
absint/) —AbstractDomain.ml,AbstractInterpreter.mldefine the fixpoint computation infrastructure. - Buffer overrun (
bufferoverrun/) — Array bounds analysis. - Concurrency (
concurrency/) — Race condition detection (RacerD). - Cost (
cost/) — Computational cost analysis. - TOPL (
topl/) — Temporal property checking. - Checkers (
checkers/) — Miscellaneous checkers (liveness, purity, annotations, etc.).
Analysis scheduling (AnalysisDependencyGraph.ml), call graph construction (CallGraph.ml), checker registration (callbacks.ml), reporting.
Very large file (~189KB) defining all command-line options. Uses CommandLineOption module (aliased CLOpt).
- 100-character line limit. Format with
ocamlformat. IStdis auto-opened in every file. Always writeopen! IStdexplicitly at the top.- Polymorphic equality is disabled. Use type-specific equality (e.g.,
Int.equal,String.equal). UsePolyVariantEqualonly for modules heavy on argument-free polymorphic variants. - Standard module aliases (use consistently, do not alias these names to other modules):
module CLOpt = CommandLineOption module F = Format module L = Logging module MF = MarkupFormatter
- Printf debugging: Use
Logging.debug_dev(triggers a warning to prevent accidental commits). - Use
[@@deriving compare, equal]for comparison/equality derivations. - Use named arguments when purpose isn't obvious, especially for bool/int params and function-typed params (conventionally named
f). - Avoid globally opening modules other than
IStdandPolyVariantEqual. - OCaml debugger: Module
Mis reallyInferModules__M(orInferBase__M, etc.) when setting breakpoints inocamldebug.
infer/src/base/Config.ml— All CLI optionsinfer/src/IR/Sil.ml— SIL instruction definitionsinfer/src/absint/AbstractInterpreter.ml— Fixpoint computationinfer/src/pulse/PulseAbductiveDomain.ml— Pulse's core abstract stateinfer/src/dune— Main dune build config (generated fromdune.common+dune.in)Makefile— Test targets and build orchestration