Skip to content

Conversation

@xymus
Copy link
Contributor

@xymus xymus commented Aug 12, 2020

Introduce availability macros defined by a frontend flag. This feature makes it possible to set the availability versions at the moment of compilation instead of having it hard coded in the sources. It can be used by projects with a need to change the availability depending on the compilation context while using the same sources.

The availability macro is defined with the -define-availability flag:

swift-frontend MyLib.swift -define-availability "_iOS8Aligned:macOS 10.10, iOS 8.0” -define-availability "_myProject 1.0:macOS 10.12, iOS 10.0" ...

The macro can be used in code instead of a platform name and version:

@available(_iOS8Aligned, *)
public func foo() {}

// Macros can be referenced with their version and be combined with other platform specifications.
@available(_myProject 1.0, tvOS 12.0, *)
public func projectFunc() {}

func client() {
  // Macros can be used for conditional availability checks.
  if #available(_iOS8Aligned, *) {
    foo()
  }

  if #available(_myProject 1.0, tvOS 12.0, *) {
    projectFunc()
  }
}

The use of availability macros in the @available specification is expanded at parsing and should not be visible in any compiler outputs. This includes the swiftinterfaces which will show the full classic availability specification. The foo function in the previous will be printed in the swiftinterfaces as:

@available(macOS 10.10, iOS 8.0, *)
public func foo()

Verion numbers, or triples, are optional on macros. A macro without an explicit version defaults to the version 0.

Availability macros can’t be used in inlinable code as it is copied textually in the generated swiftinterface files. Further work would could lift this limitation.

rdar://problem/65612624

@karwa
Copy link
Contributor

karwa commented Aug 13, 2020

What about if you could reference the availability of another declaration, as in #29559 ? Then you could set that based on normal conditionals, including standard #if defines, canImport, etc.

I feel that that approach leads to more self-documenting code than literally passing in an availability string as a compiler argument.

@xymus
Copy link
Contributor Author

xymus commented Aug 14, 2020

I see this and referencing availability as two different concerns. The compiler flag aspect of this PR is designed to compile the same source code to different availability versions, whereas #29559 still rely on availability defined in the sources. This feature allows frameworks developers to align many APIs for the same release and to backport the framework.

That being said, with this solution the availability macros remain in the hand of the framework developers and are not exposed to the framework clients who will only see the classic availability specifications. So the framework developers can use the macro to fit their need and it shouldn't prevent further improvements to the availability attributes.

@karwa
Copy link
Contributor

karwa commented Aug 14, 2020

What I mean is that you can achieve the same thing by writing:

#if DARWIN_STATIC_STDLIB // or whatever
  // @available(*)
  typealias MinimumSupportedDarwin = Void
#else
  @available(macOS 11, iOS ..., *)
  typealias MinimumSupportedDarwin = Void
#endif

And then using availability refs. This allows you to retarget the same sources to be compiled without availability (or with different availability), but it keeps the information passed through the command-line to just switches. The meaningful information is still kept as Swift source code (which is good, because debugging problems with this is likely to need source changes, and hopefully this allows for less digging through shell scripts to decipher where availability strings come from).

@shahmishal
Copy link
Member

Please update the base branch to main by Oct 5th otherwise the pull request will be closed automatically.

  • How to change the base branch: (Link)
  • More detail about the branch update: (Link)

@xymus xymus changed the base branch from master to main October 1, 2020 18:34
@xymus
Copy link
Contributor Author

xymus commented Oct 6, 2020

@swift-ci Please smoke test

xymus added 2 commits October 6, 2020 11:25
Introduce availability macros defined by a frontend flag.
This feature makes it possible to set the availability
versions at the moment of compilation instead of having
it hard coded in the sources. It can be used by projects
with a need to change the availability depending on the
compilation context while using the same sources.

The availability macro is defined with the `-define-availability` flag:

swift MyLib.swift -define-availability "_iOS8Aligned:macOS 10.10, iOS 8.0" ..

The macro can be used in code instead of a platform name and version:
@available(_iOS8Aligned, *)
public func foo() {}

rdar://problem/65612624
Availability macros can’t be used in inlinable code
as inlinable is copied textually in the generated
swiftinterface files. Further would could lift this
limitation.
@xymus
Copy link
Contributor Author

xymus commented Oct 6, 2020

@swift-ci Please smoke test

@xymus xymus requested review from beccadax and nkcsgexi October 6, 2020 18:31
@xymus xymus marked this pull request as ready for review October 6, 2020 18:31
@xymus
Copy link
Contributor Author

xymus commented Oct 6, 2020

Moving out of draft state as it should now be ready for review. I've updated the description to be up to date with the current feature design and limitations.

It sounds like the best approach here is to keep this feature simple as it would be mostly useful to framework developers with a specific need and it won’t address all use cases. The in-language alternative could be more useful to framework clients and address other Framework developers use-cases. For this reason, I redesigned the feature to be as little obtrusive as possible. It should affect the behavior of the compiler only when an availability macro is defined in the frontend flags. The implementation could be extended to associate identifiers in availability attributes to other sources than macros passed as arguments.

@xymus
Copy link
Contributor Author

xymus commented Oct 7, 2020

@swift-ci Please smoke test Linux platform

@xymus xymus changed the title [Sema] Define availability versions with a compiler flag [Sema] Define availability specification macros with a frontend flag Oct 8, 2020
@xymus xymus merged commit fa6f1b6 into swiftlang:main Oct 8, 2020
@xymus xymus deleted the expand-avail branch November 2, 2021 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants