What does @frozen on an enum mean for you as an API author?

1.10.5 · L5 · Learning

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 default on non-frozen SDK enums. The compiler will warn, but a plain default silences 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 — @frozen on 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… →