ADR-370: A Function Asks to Be Inlined With @inline; the Compiler Adds the Hint Itself Only Where It Knows Better

Status: Accepted Date: October 19, 2026 Answers: what a Nikaia program can do when the optimiser below leaves a hot call out of line, and how far the compiler takes that decision off the program’s hands Related: ADR-296 D41 (what a fold’s step calls is written #[inline]), ADR-286 D19 (each package is a crate of its own), #695 (whether a map’s entry is inlined depends on the codegen units)

1. Question

@inline
fn row(b: Bytes, i: i64) -> i64 { … }

Inlining copies a called function’s body into the caller: the call goes, and the optimiser sees across it. The language below decides it by heuristics, and a Nikaia program has no word for it. A hand-written 1BRC program measured what that costs: a row function called from two places stayed a call, +49 instructions a row; a shared add for the scan and the merge, +40; the program wrote the same code twice to avoid both. And because each package is a crate of its own, a pub fn of another package is never inlined without a hint unless the whole build is linked with LTO.

2. How others do it

3. Decision

D1 — @inline asks, @inline(always) insists, @inline(never) forbids.

An attribute before a function or a method, in the @ form the language has (@detached, @frame): @inline is a hint, and makes a pub fn inlinable in another package; @inline(always) asks that every call be inlined; @inline(never) that none be, for a cold path such as an error’s. None of them changes what a program means, only how it is built. A function that calls itself is never inlined into itself; always then reaches its other callers.

D2 — The compiler adds the hint itself where it knows better than the optimiser below.

As a program relies on its systems language’s optimiser instead of writing assembly, a Nikaia program relies on its compiler, which derives much that another language asks to be written - and an inlining hint is one of those things. The compiler writes an inlining hint where its own knowledge of the program shows a call that is hot and that the current backend leaves out of line: ADR-296 D41’s fold step is the first case. A case is added only when it is obvious, measured, and the backend’s version is named in the record that adds it; this record does not ask for more than D41 today. A written @inline(never) wins over the compiler’s hint.

4. Rejected alternatives

5. What this does not decide

</content> </invoke>

This site is open source. Improve this page.