Crowd source: Swift Language Modes in various environments

There is so much counterintuitive information in the transition from Swift 5 to Swift 6. Many people don't understand the difference between Swift compiler versions and language modes. Swift 6 understandably introduces new compiler errors which are breaking changes. But these compiler errors appear in surprising places as well.

For example, the docs state "The Swift 6 language mode is opt-in . Existing projects will not switch to this mode without configuration changes." (Quote from “Migrating to Swift 6 | Documentation”) So when I built my SPM project, I did not expect strict concurrency checking to produce non-compilable errors. But it did. If Swift 6 language mode is supposed to be opt-in then why would this result in an error, instead of a warning?

Well it seems that the docs are incorrect because the errors went away after I opted out of Swift 6 language mode, and opted into Swift 5 language mode.

It seems that Xcode, SPM, and Swift CLI all handle this slightly differently.

For this reason, I'd like to crowd source some info about how Swift behaves differently depending on tools version, language mode, etc.

I would appreciate anyone willing to contribute to this spreadsheet.

This sounds like a bug in how the compiler is emitting diagnostics.
Can you share a reproducer?

Thanks. I'll DM you.

I don't hack on that part of the compiler much, but I'm happy to take a look. Never wrong to file a GitHub issue or a Feedback though :)

Ah, I see what's going on.

Basically, there's more than one way to opt-in to the Swift 6 language mode, and you've done so without knowing it, as detailed in "Enabling The Swift 6 Language Mode"

A Package.swift file that uses swift-tools-version of 6.0 will enable the Swift 6 language mode for all targets. You can still set the language mode for the package as a whole using the swiftLanguageModes property of Package.

This is why you have to opt your target back out of the Swift 6 language mode in your package manifest. You can instead downgrade the minimum tools version.

2 Likes

Ah. Of course. Thank you. I missed that detail.

A Package.swift file that uses swift-tools-version of 6.0 will enable the Swift 6 language mode for all targets.

It's the swift package init command who creates the // swift-tools-version: 6.0 line in Package.swift file, not user. So for Swift Package Manager new projects we have opt-out, not opt-in.

2 Likes

This is a very good point. I did not add // swift-tools-version: 6.0 to my Package.swift. It was swift package init that did. It is very misleading for the docs to say that it is opt-in when it implicitly opts in for me without my knowledge.

It’s opt-in for existing projects, not new projects.

What language mode do new Xcode projects have?

Edit: I found the answer here: Adopting strict concurrency in Swift 6 apps | Apple Developer Documentation

new projects default to the Swift 5 language mode.

Swift Package Manager behaves differently.

1 Like

Perhaps swift package init should add a comment detailing the effects of different swift-tools-version settings.

1 Like

I've always wanted to see swift-tools-version renamed to minimum-swift-tools-version (or something like that). The word minimum is important here!

1 Like

Except it's not accurate. swift-tools-version determines the version SPM uses to parse the manifest exactly, and only newer versions get newer features. This includes things like language mode, but also things like the updated manifest model with the swiftLanguageMode label. Newer versions of SPM will happily parse and use packages with much older tools versions, and packages can require language versions newer than the tools version.

2 Likes

Would you say the documentation is accurate?

The Swift tools version declares the version of the PackageDescription library, the minimum version of the Swift tools and Swift language compatibility version to process the manifest, and the minimum version of the Swift tools that are needed to use the Swift package.

Yes, so I suppose I should've said it's incomplete, rather than inaccurate. It's a minimum in some ways, but in most it determines the exact version of behavior used to interpret the package.

1 Like

Semi-related to the discussion here, I think it might be a good idea to think more about the tools-version and its relation to language mode, as well as revisit the concept more generally.

It was designed in a somewhat different world where language versions were happening more often and were generally something developers would adopt rather quickly. Similarly, on the package manager side, the version was mostly about additions to the API, rather than actually different behaviors preserved for backwards compatibility.

4 Likes