Standard Library Polyfills Package

So I was just disappointed to learn that the new Identifiable protocol is restricted to iOS 13+ even though it is a part of the Standard Library: Identifiable restricted to iOS 13 for SPM packages?
Also this directly contradicts the docs which indicate it's available in the Xcode 11 SDK:
Apple Developer Documentation

I had grown accustomed to being able to use all of the new Standard Library features whenever I bumped my Swift version, but I guess this was contingent on bundling the runtime + standard library with applications.

Once the ABI was stabilized, new standard library features became locked to a platform version (given the platform is now responsible for providing the standard library and runtime) even though they may not use any newer language features (e.g. Identifiable). This makes these "currency types" all but worthless as library authors won't be able to use them for many years, or they'll have to write their own polyfills.

Similar to the Swift Standard Library Preview Package whose proposal is now in review, I'd like to propose a Swift Standard Library Polyfills package. This library would backport standard library features to the minimum platform that would support their functionality. E.g. I'm pretty sure Identifiable could have worked since at least Swift 2.0 / iOS 8.0.

Additionally, we really need platform+version conditional compilation blocks to match SPM,
e.g. #if !os(iOS(.v8)), which can be hacked with dummy libraries with platform requirements but ideally should be included in the conditional compilation blocks.

The library would include something like:

#if !canImport(iOS13) || !canImport(macOS10_15) || ...
public protocol Identifiable {

  /// A type representing the stable identity of the entity associated with `self`.
  associatedtype ID: Hashable

  /// The stable identity of the entity associated with `self`.
  var id: ID { get }
}
#endif

This way we could use the Identifiable protocol on an application targeting iOS 10, and we would compile the polyfill Identifiable for iOS 10, 11, and 12, but it would not be compiled on 13+.

At the usage site, you would have to import SwiftPolyfills:

import Foundation
import SwiftPolyfills

struct User: Hashable, Identifiable {
  let id: String
  let name: String
  let birthday: Date
}

And now 3rd party libraries could share the polyfill implementations, and consumers would only pay to backport features to their minimum deployment target.

3 Likes

There’s this Backwards-deployable Conformances post not long ago. You might wanna check it out.

1 Like

The "Polyfill" approach @jrose describes is similar, except I'm proposing a Swift package which uses compile-time macros to backport if necessary. Developers would have to intentionally draw a dependency on the SwiftPolyfills package to use a backported API, and they would pay the cost of carrying that code with them in their binaries (though presumably their standard library would be lighter by a similar amount).

The main "Con" with my proposed approach is that you might have slightly different implementations of the polyfill vs. what is in the standard library, though in practice I feel the risk is minimal since the standard library is open source and we can copy the code verbatim.

Where this could potentially run into some issues is when the standard library implementation relies on other standard library APIs which are also new but could be reimplemented other ways. You could wind up with different implementations of the same API which behave slightly differently. For something as simple as Identifiable, though, the risk would be nonexistent.

1 Like

I like this idea a lot and would love to see it. I was similarly disappointed when standard library features started requiring minimum OS versions.

For something like Identifiable, it would be trivial for many folks to make their own copies where needed, but having a common library would be great for library authors.

About the compiler conditional blocks: couldn't you use this: #if available(iOS 13)