What does @frozen on an enum mean for you as an API author?
Predict first
A library ships a non-frozen public enum Mode { case light, dark }. What must a client switch include?
switch mode {
case .light: ...
case .dark: ...
// ?
}
- Nothing more
- @unknown default
- A fatalError
Mental model. Frozen is a promise carved in stone: no new cases, ever. The reward is exhaustive switches on the client side.
@frozen promises the enum will never gain a case. Clients can switch exhaustively without @unknown default, and the compiler can lay out the type with a known size.
Adding a case later is an ABI break — old clients have code paths that do not handle it. Frozen is appropriate for a closed set that genuinely cannot grow (a math result, a fixed protocol state), not for anything product-facing.
A non-frozen enum from a resilient library may gain cases later, so clients add @unknown default. @frozen promises it never will.
Common traps
- Freezing a public enum “for performance”. The performance gain is small; the compatibility cost is permanent.
- Forgetting
@unknown defaulton non-frozen SDK enums. The compiler will warn, but a plaindefaultsilences the warning and hides future cases.
They might follow up with
- What is a resilient enum? The default for library-evolution builds: size is hidden, and clients must handle unknown cases.
- Can a frozen struct be changed? No —
@frozenon a struct freezes its stored-property layout too.
Related questions
- 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 is ABI stability vs source compatibility vs module stability? You need to add a field to a public struct in a binary SPM library… →