# Aleksey Kladov - Inline in Rust (Highlights) ![rw-book-cover|256](https://readwise-assets.s3.amazonaws.com/static/images/article1.be68295a7e40.png) ## Highlights - It gives the compiler the necessary context to apply further transformations. - To achieve separate compilation, compilers expose signatures of functions, but keep function bodies invisible to other modules, preventing inlining. - In Rust, a unit of (separate) compilation is a crate. - it enables cross-crate inlining. - the compiler implements this by compiling a separate copy of the #[inline] function with every crate it is used in, significantly increasing compile times. - Besides #[inline], there are two more exceptions to this. Generic functions are implicitly inlinable. - The other exception is link-time optimization. LTO opts out of separate compilation ### Inlining in Practice - First, it’s not a good idea to apply #[inline] indiscriminately, as that makes compile time worse. If you don’t care about compile times, a much better solution is to set lto = true in Cargo profile https://doc.rust-lang.org/cargo/reference/profiles.html#lto - Second, it usually isn’t necessary to apply #[inline] to private functions — within a crate, the compiler generally makes good inline decisions. - Third, when building an application, apply #[inline] reactively when profiling shows that a particular small function is a bottleneck. - Fourth, when building libraries, proactively add #[inline] to small non-generic functions. Pay special attention to impls: Deref, AsRef and the like often benefit from inlining. A library can’t anticipate all usages upfront, it makes sense to not prematurely pessimize future users. - Fifth, mind generic functions. It’s not too wrong to say that generic functions are implicitly inline. As a result, they often are a cause for code bloat. - Separate-compilation friendly private implementation. #rust #example #code code block ``` // Public, generic function. // Will cause code bloat if not handled carefully! pub fn parse_str(wat: impl AsRef<str>) -> Result<Vec<u8>> { // Immediately delegate to a non-generic function. _parse_str(wat.as_ref()) } // Separate-compilation friendly private implementation. fn _parse_str(wat: &str) -> Result<Vec<u8>> { ... } ```