What are @usableFromInline and @inlinable in relation to access control?

1.7.4 · L5 · Learning

Mental model. @inlinable ships a photocopy of your function body to the client. Everything that body touches must also be shippable.

@inlinable puts a function's body into the client's module so it can be specialized and inlined across module boundaries. The body may only reference public or @usableFromInline declarations.

@usableFromInline keeps a declaration internal for source but makes it part of the ABI so inlinable code can call it. Over-using inlinable bloats binaries and freezes implementation details you can no longer change without breaking clients.

Common traps

  • “@inlinable is always a performance win.” It trades binary size and future flexibility for call-site speed.
  • Forgetting the propagated constraint. Marking one function inlinable forces its callees to be public or @usableFromInline, and that cascades.

They might follow up with

  • What is library evolution mode? A build mode that hides layout and dispatches through resilient accessors so you can change a library without recompiling clients.
  • Does @inlinable affect ABI stability? It makes the body part of the contract — changing it changes what clients run, even without relinking.

Related questions

  • 1.3.8 How do you evolve a public protocol without breaking clients?
  • 1.10.4 What is ABI stability vs source compatibility vs module stability?
  • 1.10.6 You need to add a field to a public struct in a binary SPM library used by five apps. What do you consider?

← What does package access solve?