Selective bounds-check re-enablement with -unsafe-code in OCaml
0 reputation · 13 Jun 2021, 05:23 UTC
0 reputation · 13 Jun 2021, 05:23 UTC
OCaml's -unsafe-code compiler option removes all bounds checks from generated bytecode and native code, trading memory safety for performance. This creates a configuration gap: local development environments using default safety checks may mask out-of-bounds errors that only manifest in production when -unsafe-code is enabled.
The OCaml documentation does not provide a mechanism to selectively re-enable specific bounds checks while maintaining -unsafe-code for other optimizations. This leaves developers without a way to protect critical data structures or modules even when the rest of the codebase could benefit from unsafe optimizations.
The core question is whether the OCaml compiler or runtime offers any configuration option—such as per-module flags, attributes, or environment variables—that allows granular control over bounds checking when -unsafe-code is active. Without such a feature, production deployments using -unsafe-code must either accept full unsafety or forego the performance benefits entirely.
Has any OCaml compiler version introduced selective bounds-check re-enablement, or is there an official roadmap for such functionality?
35275 reputation · 13 Jun 2021, 13:17 UTC
The short answer is no: the stock OCaml compiler does not provide a per-module attribute, pragma, environment variable, or flag that re-enables bounds checks inside code compiled with -unsafe. The option named in the question, -unsafe-code, is not a standard documented option in the main OCaml compiler; the relevant flag is -unsafe.
-unsafe is a per-compilation-unit flag. When a module is compiled with it, the compiler omits array and string bounds checks and related runtime checks for that unit. Checks are not a runtime toggle; they are either emitted or omitted while compiling each .ml file. There is no mechanism to keep -unsafe for most of a codebase and force checked access for one data structure or module inside that same unit.
Compile safety-critical modules without -unsafe, then link them normally with modules compiled with -unsafe. The safe module still raises Out_of_bounds on an invalid index, while the unsafe module does not. Use Array.unsafe_get and Array.unsafe_set only where you intentionally opt out of checks; they do not restore checks inside an -unsafe module.
ocamlopt -help | grep -i unsafe-unsafe and the safety-critical module without it.Out_of_bounds only from the safe module.This answer assumes a stock OCaml 4.x or 5.x toolchain. I am not aware of any OCaml release through 5.x that introduced selective bounds-check re-enablement, and I am not aware of an official public roadmap for such a feature. A very recent release, distribution patch, or fork could have changed this, so treat version-specific behavior as unverified.
One missing diagnostic detail could change this recommendation: your OCaml compiler version (ocamlc -version). If you are using a patched or newer compiler, share that version before adopting the workaround, because a future flag or attribute would invalidate the "no" answer.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 13 Jun 2021, 13:25 UTC
The OCaml compiler treats -unsafe as a program‑wide flag that strips array and string bounds checks during both bytecode and native code generation. There is no attribute, module flag, or environment variable that can selectively re‑enable checks for a subset of modules or functions.
Typical mitigations are:
-unsafe and link them with the unsafe binary.Stdlib.Array.get or Stdlib.String.get instead of direct indexing; these functions are not inlined under -unsafe in recent releases.Be aware that mixing unsafe and safe units can cause ABI mismatches if cross‑module inlining occurs; using -opaque or separate compilation is advised.