How to entirely forbid a function being inlined?

I've found the #[inline] attribute, which has the following behavior according to the Rust Reference:

There are three ways to use the inline attribute:

  • #[inline] suggests performing an inline expansion.
  • #[inline(always)] suggests that an inline expansion should always be performed.
  • #[inline(never)] suggests that an inline expansion should never be performed.

Note: #[inline] in every form is a hint, with no requirements on the language to place a copy of the attributed function in the caller.

However, I don't want to "suggest" that my function not be inlined, I want to force the compiler to not inline it. Is there a way I can do this in Rust?

To what end? That is, which of the several reasons you could be interested in the layout of the generated code is important to you?

1 Like

Unless you're willing to implement your own back end (like LLVM), this is impossible. #[inline(never)] is as close as you're going to get, as only laughably simple cases get inlined.


If you're doing this for the purpose of messing with the assembly code at runtime, simply include an inline assembly block with an exported label. Rust specifically forbids the compiler from assuming that the contents of an inline assembly block are the instructions that will actually be executed, and can only check stuff declared in the options (except that the linker can observe its actual size in bytes).

Oops, sorry, the above is wrong:

  • You cannot assume that an asm! block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the asm! block, for example when the function containing it is inlined in multiple places.

IIRC the only way guaranteed is to dynamically link the function at runtime.

  1. While the code inside the function is running, I want tools that profile the function based on stack frames to be able to see a stack frame corresponding to this function (which goes away if the function is inlined).
  2. I want to be able to inspect the binary and find the assembly code for the function as a function, which isn't guaranteed to still exist in the final binary if the function is inlined (yes, it could be optimized out entirely if the optimizer shows it isn't needed, but I'm fine with that risk).

Just use #[inline(never)] and call it a day. You're probably not going to run into a case where it's inlined.

1 Like

Note that LLVM still const propagates arguments even into #[inline(never)] functions afaik. And it propagates inferred attributes like pure outwards which may allow the call to be removed entirely.