The Curiously Recursive Inlinable Switch Pattern (CRISP)
Jordan Rose (via tweet):
When inlinable code switches over a non-frozen enum, it has to handle possible future cases (since it will be inlined into a module outside the standard library). You can see this in action with the implementation of
round(_:)
in FloatingPointTypes.swift.gyb, which takes a FloatingPointRoundingRule. It looks something like this:[…]
Making
round(_:)
inlinable but still have a default case is an attempt to get the best of both worlds: if the rounding rule is known at compile time, the call will compile down to a single instruction in optimized builds; and if it dynamically turns out to be a new kind of rounding rule added in Swift 25 (e.g..towardFortyTwo
), there’s a fallback function,_roundSlowPath(_:)
, that can handle it.
It looks like the function is calling itself, but it’s actually calling a future version of itself that is guaranteed not to recurse.
Previously: Swift Proposal: Non-Exhaustive Enums.