Motivation
Scanning through the Swift Standard Library at a high level and looking at some of the newer additions, we can see something like this:
@available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
@frozen
public struct DiscontiguousSlice<Base: Collection> { ... }
@available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension DiscontiguousSlice { ... }
@available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension DiscontiguousSlice.Index: Hashable
where Base.Index: Hashable {}
@available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
extension DiscontiguousSlice: Collection { ... }
There is lots of repetition here, as I'm sure anyone who's written many of these availability checks will sympathise with. It also could be seen as a "leaky abstraction" of the underlying target platforms. As I understand it, the availability checks are necessary on ABI stable platforms to ensure that the standard library features are available on the target platform, because the platform itself provides its own copy of the Swift runtime and standard library. This informs the compiler to enforce uses of #available
/ @available
as necessary to prevent compilation in the event that an unavailable call is made.
However, we see above that this becomes very repetitive very quickly. Additionally, as Swift reaches new platforms, it seems like this level of "connection" to a given vendor's specific platforms is somewhat restrictive and will only get worse as more platforms are added.
Proposed Solution
The least disruptive and backwards compatible solution appears to be Platform Aliasing, which can reduce an annotation like this...
@available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
...to something as simple as this...
@available(apple 2020, *)
The apple
platform name in this example corresponds to a "Platform Alias" which implicitly references any number of other platforms. Versions of the alias then correspond to specific versions of the underlying platforms. The versioning example here is year-based, with the minor version indicating the iteration of the software released for that year. Any other alternatives are also possible, of course. Pseudocode:
apple <- macOS, iOS, watchOS, tvOS
apple 2020.1 <- macOS 10.16
<- iOS 14.0
<- watchOS 7.0
<- tvOS 14.0
## other platforms still use 2020.1 versions
apple 2020.2 <- iOS 14.1
Examples:
// uses 2020.2 versions
@available(apple 2020.2, *)
// uses 2020.1 versions
// (earliest supported platforms for this year)
@available(apple 2020, *)
This works especially well for Apple platforms as software releases of their respective platforms are generally released at similar times supporting the same new features as each other. I imagine these Platform Alias definitions will have to be hard-coded into the compiler (i.e. they are not user-configurable) but seeing as platform definitions themselves are non-configurable from user code, this is not a real negative (given that sensible defaults are provided by the platform vendors).
Apologies if something similar to this has been pitched before, I had a good look and was unable to see anything. Please let me know your thoughts or if I'm coming at this from totally the wrong angle!