Swift function back deployment

Apr 01, 2023#swift#attributes

Function back deployment, achieved by using a new @backDeployed(before: ...) attribute that was introduced in Swift 5.8, is a feature that extends the availability of a function to platforms versions prior to the introduction of that function.

The @backDeployed attribute used to indicate that a copy of the function should be emitted into the client to be used at runtime when executing on an OS prior to the version identified with the before: argument.

When a function with @backDeployed is called, the compiler wraps the invocation of the function in a thunk. The thunk checks whether the library entry point for the declaration is available at runtime, and invokes it if it is. Otherwise, a copy of the function that was emitted into the client is called instead.

This attribute may apply to functions, methods, and subscripts. Properties may also have the attribute as long as the they do not have storage. There are rules that limit which declarations may be back deployed:

  • The declaration must be public or @usableFromInline.
  • Only functions that can be invoked with static dispatch.
  • The declaration should be available earlier than the platform versions specified in @backDeployed (otherwise the fallback functions would never be called).
  • The @_alwaysEmitIntoClient and @_transparent attributes are incompatible.
  • Declarations with @inlinable.

The body may only reference declarations that are accessible to the client, such as public and @usableFromInline declarations. Similarly, those referenced declarations must also be at least as available the back deployed function, or if #available must be used to handle potential unavailability.

// A library that provides some math functions
public struct MathKit {
    // A function that calculates the factorial of a number
    // This function was introduced in iOS 15.0
    @available(iOS 15.0, *)
    public func factorial(_ n: Int) -> Int {
        if n <= 1 {
            return 1
        } else {
            return n * factorial(n - 1)
        }
    }

    // A function that calculates the Fibonacci sequence up to a given number
    // This function was introduced in iOS 16.0, but we can use it on iOS 15.0 
    // and later thanks to @backDeployed
    @backDeployed(before: iOS 16.0)
    @available(iOS 15.0, *)
    public func fibonacci(_ n: Int) -> [Int] {
        var result: [Int] = []
        var a = 0
        var b = 1
        while a < n {
            result.append(a)
            let c = a + b
            a = b
            b = c
        }
        return result
    }
}