5.11 · Package access, SPI, internal imports, strict memory safety and pre-specialisation
The finer controls of a module boundary: who can see a declaration, who has to import a dependency, which unsafe code is marked, and how a library offers specialised generics.
Mental model. Beyond public and internal there are four more dials on what crosses a module: package, SPI, import visibility and unsafe marking.
Who can see what
package, @_spi and import access levels.
- How do package access and @_spi differ from public and internal, and what do they look like in a .swiftinterface?
package access is visible to every module compiled with the same package name (-package-name, set by SwiftPM from the package manifest) and to nobody else.… - What does internal import (SE-0409) change, and why does it matter for API leakage and build times?
Without it, a plain import Dep in any file makes Dep visible to the whole module and, since it is effectively public, lets Dep’s types appear in public API…
Safety and speed at the edge
Strict memory safety and exported specialisations.
- What is strict memory safety (Swift 6.2), what does the unsafe keyword mark, and what does it not do?
Swift is memory safe except where you reach for unsafe constructs: UnsafePointer and friends, unsafeBitCast, unchecked Unmanaged, C pointers. Strict memory… - How can a library with library evolution still offer a fast generic function, and what does @_specialize(exported: true) do?
In a library built with -enable-library-evolution a generic function that is not @inlinable compiles once, takes the type through metadata and witness tables…
More in Compiler & language internals
- 5.1 · From source to machine code, and how to look inside
- 5.2 · Devirtualisation, whole-module optimisation, inlining, exclusivity
- 5.3 · Specialisation, witness tables, and opaque vs existential in the compiled code
- 5.4 · Library evolution, module interfaces, and the ABI boundary
- 5.5 · How Swift macros work, and the roles they play
- 5.6 · Why it compiles slowly, and what rebuilds
- 5.7 · Swift 6 language mode and upcoming features
- 5.8 · Symbol names, linkage, lazy globals and reflection metadata: what is in the binary
- 5.9 · Optimisation levels, closure contexts, ownership conventions and value layout
- 5.10 · What property wrappers, result builders, async and throws compile to