SE-0435: Swift Language Version Per Target

Hello Swift community,

The review of "Swift Language Version Per Target" begins now and runs through May 13, 2024. The proposal is available here:

https://github.com/apple/swift-evolution/blob/main/proposals/0435-swiftpm-per-target-swift-language-version-setting.md

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager by email. When emailing the review manager directly, please include "SE-0435" in the subject line.

Trying it out

If you'd like to try this proposal out, you can download a toolchain supporting it here. Any trunk development snapshot dated April 11, 2024 or later should do.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

  • What is your evaluation of the proposal?
  • Is the problem being addressed significant enough to warrant a change to Swift?
  • Does this proposal fit well with the feel and direction of Swift?
  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/main/process.md

Happy reviewing,

—Becca Royal-Gordon
SE-0435 Review Manager

24 Likes

I'm strongly in favor of this proposal.

Yes, right now it's not possible to migrate a package to Swift 6 module-by-module; it's all or nothing for the entire package, which makes migrating a package to Swift 6 more difficult.

Yes, Swift has supported per-module migration to new language modes for years to facilitate incremental migration. SwiftPM already supports enabling upcoming features via SwiftSetting.enableUpcomingFeature to make incremental progress toward migrating to a new language mode, and it seems obvious that it should provide the same support for the language mode itself.

I have not used other languages or libraries with similar features.

I participated in the pitch discussion and read the proposal again before leaving this review.

10 Likes

I think this makes a lot of sense (and read the proposal and was part of the pitch discussion), and this is inline with similar previous features and facilitates module-by-module migration, which is great. So +1 for this proposal, no reservations really.

One small comment (for both this proposal and future ones) - its in general great to add a use-site example of new API proposed even if easy/straightforward, it helps a lot in cognitive load navigating what it's all about and is much appreciated - just a friendly suggestion for the future. :slight_smile:

I do still think that the default toolchain language mode selection (when not using SwiftPM and selecting tools/language versions there) is a bit strange as it seems we are stuck at Swift 5 as the default for all eternity? But that's for another discussion - so anyone interested in that can follow up there.

8 Likes

Looks good. I tried the toolchain and found no issues

  • Both .v6 and .v5 are defined
  • Changing the target language version (even by omission) causes swift build to (properly) rebuild the target
    • Changing between an inferred swift-5 to an explicit .v5 (properly) did not cause a rebuild
  • #if swift(<6) and #if swift(>=6) worked as compile-time branches in the code.

For users looking to learn this feature from the proposal, would you consider including all that in the proposal as expected details/results? It might reinforce the language/tool distinction to note that #if swift(..) will see (language) swift-5 when the swift-6 tools run in swift-5 mode.

(Also is there an implementation PR? I couldn't find it searching for SE-0435.)

Given the default of swift-5 even with swift-6 tooling, not discussed in this pitch/review was an additional converse flag at the package level to default or force all package targets to swift-6 (or a command-line flag for all targets of all packages being built). That could simplify the happy path for swift-6 investigation/migration for developers integrating other packages. I assume that would be rejected or deferred as low-traffic, possibly confusing d/t noise, and better added later in the swift-6 lifecycle when swift-5 code and default versions are the exception rather than the rule...

But that might offer a vehicle to simplify the combinatorics of swift versioning X package versioning that leads to a consumer Package@{version}.swift needing to know the swift-[5|6]-compatible library package version. It would be nice if the library package providers could specify that their package could build in either mode, so the consumer build setting would drive it into v5 or v6 mode. That may be unrealistic because the language differences are not really (or best) managed with #if's, and require a version branch anyway.

Edit: I imagined the latter as a new conditional, where the library target specifies a second permitted version available when overridden.

1 Like

Thank you, I will add that!

1 Like

Implementation PR - Implement per target swift version selection by xedin · Pull Request #7439 · apple/swift-package-manager · GitHub (mentioned in the header of the proposal).

2 Likes

I am strongly in favor of the proposal.

Yes. I believe the migration to Swift 6 language mode will be challenging as developers come up to speed with all that strict concurrency entails.

Being able to specify the language version by target will give developers a great deal of flexibility in migration.

This is true not only for the impending transition to Swift 6 language mode, but also for all future language modes, so it is incredibly useful in the near term and continues to be in the future as well.

Yes, modeling this as a SwiftSetting that takes a SwiftVersion and optional BuildSettingCondition fits existing usage. Using SwiftSetting is appropriate since those generally map to compiler flags. Finally the swiftLanguageVersion matches the naming convention of the existing swiftLanguageVersions.

This functionality has been available in Xcode projects for as long as Swift has had language modes.

In Xcode it is handled as a build setting per target. The analogous thing in Swift PM would be a SwiftSetting per target.

I followed the pitch and read the proposal.


One minor correction:

I believe the reference to SwiftLanguageVersion in the “Alternatives considered” section should just be SwiftVersion.

2 Likes

I strongly agree with this.

I would be in favor of inclusion of a use-site example as a standard part of API proposals. It really does help me understand a proposal by seeing the proposed API in use.

2 Likes

Thank you all for your feedback! SE-0435 has been accepted as-is; please see the announcement for more details.

3 Likes