The Evolution of Swift's Standard Library
One of the primary design goals of Swift is to allow efficient execution of code while allowing load-time abstraction of implementation, according to a work-in-progress document by Apple. Apple’s document provides information that is relevant to library designers, including Swift’s Standard Libraries.
One of the main requirements that library designers face is compatibility between future clients and existing versions of their library (forward compatibility) and between existing clients and future versions of the library (backward compatibility).
These requirements can be satisfied by making sure that code written against a published interface will continue to function while the underlying implementation changes provided the original interface is still satisfied.
The discussion that Apple is driving forward about library evolution aims to influence Swift's design and features so they better suit the goal of enabling forward and backward compatibility without incurring too a high cost due to load-time checks.
Apple’s document tries to define a set of practices that can help library designers to reach that goal, including:
- using a versioned API to ensure that a client that needs a particular version of an API can restrict itself to run only when that version is available;
- allowing only changes that are guaranteed not to break compatibility. To this end Apple is striving to document all kind of changes that are safe when releasing a new version of a library. Examples of such changes include modifying the body of a function, changing internal parameter names, or adding default values to parameters. On the other hand, other changes would be ruled out, such as changing a function’s generic requirements, or reorder parameters. Apple's document goes beyond functions, and tries to provide guarantees for other types, such as structs, enums, protocols, classes, extensions, and so on.
Furthermore, pursuing load-time abstraction can exact a cost in terms of optimization, Apple say. Indeed, many optimizations depend on the actual implementation of a feature, i.e., whether it accesses global memory or not, or the number of members in a
struct, and thus a client that wants to be backward and forward compatible should strive to avoid such optimizations.
Other areas of concern are with inlineable code, which should be considered as being outside of the current module, because it will be finally included in the client’s module; local availability contexts, which affects how the `#available` construct applies to function bodies; promises about types, such as stating that a type is `trivial` or declaring its maximum `size_in_bits`, and a few more.
As mentioned, the document is a work in progress and still subject to fundamental changes, but it’s still worth keeping an eye on if you are a Swift developer.