Leveraging @availability for PackageDescription APIs

So far evolution of the PackageDescription library required shipping a new version of the library because of breaking changes in the API. As the project is maturing, we're seeing more additive changes instead of breaking changes (deployment target, build settings). This is generally good news as it means less maintenance cost for SwiftPM. However, because the APIs in newer tools version shouldn't be available in older tools version, it can lead to poor diagnostics and interaction with IDE-like features like autocompletion and module interface generation.

SwiftPM currently implements a runtime check to determine if you're using an API that you're not supposed to use in the current tools version. This works reasonably well but doesn't provide great diagnostics like source location and the runtime checks presents a greater maintenance burden in SwiftPM. It also won't stop tools like SourceKit from providing autocompletion for APIs that are not in available in the current tools version.

This problem is already solved in the Swift compiler for platforms and swift version using the @available attribute. We can leverage this infrastructure and expose a new private availability kind _PackageDescription to solve the problems described above. The APIs in PackageDescription library will be marked with this new availability kind as appropriate and SwiftPM will parse manifests by passing the manifest's tools version using the new (hidden) command-line option -package-description-version. Note that all of these changes will be in the compiler and package manger. Users will not be required to make any change to use this new enhancement.

The PR for compiler changes is here: Extend @available to support PackageDescription by aciidb0mb3r · Pull Request #21110 · apple/swift · GitHub



This sounds excellent to me!

1 Like

One note: the reason SwiftPM can get away with this is because it's doing a static check. There's no equivalent to #available for SwiftPM versions where you dynamically need to check which PackageDescription is in use, because package manifests are always "executed" immediately.