Skip to content

Commit b1a1f63

Browse files
committed
Release post-26
1 parent 8f242cd commit b1a1f63

File tree

2 files changed

+144
-1
lines changed

2 files changed

+144
-1
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
---
2+
title: 'Am I Using Swift 5 or 6?'
3+
slug: am-i-using-swift-5-or-6
4+
date: 2024-11-19
5+
topics: ["Swift 6"]
6+
description:
7+
---
8+
9+
Swift is in the middle of a transition from Swift 5 to Swift 6. This transition is not as simple as it may seem. In this post, we will discuss how to determine which version of Swift you are using. But first we need to clear up some misconceptions.
10+
11+
1. We need to understand the difference between Swift 6 **the compiler** and Swift 6 **the language mode**.
12+
2. We need to understand how to determine which version of the Swift **compiler** we are using.
13+
3. We need to understand how to determine which version of the Swift **language mode** we are using.
14+
4. We need to understand how to opt in or out of Swift 5 or Swift 6 **language mode**.
15+
16+
> **Note:** This post will be primarily concerned with the native Swift Package Manager. Xcode has been known to behave slightly differently than SPM, and this post does not exhaustively cover all the ways Xcode may differ. This post assumes that you know how to use SPM and particularly how to declare a Swift Package using a `Package.swift` file. If you are not familiar with this, I recommend reading the [Swift Package Manager Documentation](https://swift.org/package-manager/).
17+
18+
## What's The Difference Between The Compiler and The Language Mode
19+
Swift updates its language using semantic versioning. This means that each minor release (for example from 5.9 to 5.10) is a non-breaking change, and each major release (for example from 5 to 6) is a breaking change. A non-breaking change means that code written in the previous version of Swift will compile and run in the new version of Swift. A breaking change means that code written in the previous version of Swift will not compile in the new version of Swift.
20+
21+
>Don't forget that in Swift, the compiler will refuse to compile code that has a compiler **Error**. But if you have a **Warning**, it will still compile.
22+
23+
But Swift is also backwards compatible with prior versions of Swift. This means, for example that code written in Swift 5 can be compiled with the Swift 6 compiler. Swift 5 code can also call Swift 6 code, and vice versa. So how does this work? How can they be compatible if a major release is a breaking change. At least part of the answer is by using a Swift compiler feature called **language mode**.
24+
25+
>Note: Swift appears to have recently changed the name of this feature from **language versions** to **language modes**. You can see this in the Swift Package Manager API. (See the docs [here](https://developer.apple.com/documentation/packagedescription/package/init(name:defaultlocalization:platforms:pkgconfig:providers:products:dependencies:targets:swiftlanguageversions:clanguagestandard:cxxlanguagestandard:))). I welcome this change as "language version" was easier to confuse with the compiler version. Pay extra attention whenever you see the term "language version" in the Swift documentation or tooling. Ask yourself if it is referring to the Swift compiler version or the Swift language mode.
26+
27+
The takeaway that I want you to get is this: **Each Swift compiler can compile syntax from earlier versions of Swift**. This is done by setting the **language mode**. The compiler version determines the Swift language features that are available to you on your machine. The language mode determines which Swift syntax and language features you would like to use in each target.
28+
29+
## How To Determine Which Version of The Swift Compiler You Are Using
30+
Now that we understand the difference between the Swift compiler and the Swift language mode, let's talk about how to determine which version of the Swift compiler you are using. Open terminal and type in the following command:
31+
32+
```bash
33+
swift --version
34+
```
35+
36+
If you have Swift installed on your machine, then you should see something like this:
37+
38+
```bash
39+
swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
40+
Target: arm64-apple-macosx15.0
41+
```
42+
43+
This shows you the tooling version of the Swift compiler. In this case, it is Swift 6.0.
44+
45+
## How To Determine Which Version of The Swift Language Mode You Are Using
46+
Now that we know how to determine which version of the Swift compiler we are using, let's talk about how to determine which version of the Swift language mode we are using.
47+
48+
Swift allows us to mix and match Swift 6 code with prior versions. At present, the Swift 6 compiler can use the following language modes:
49+
- Swift 6
50+
- Swift 5
51+
- Swift 4.2
52+
- Swift 4
53+
54+
The Swift documentation states [here](https://arc.net/l/quote/rrrnddoa) that the default language mode is Swift 5. This means that if you do not specify a language mode, then the Swift 6 compiler will use the Swift 5 language mode. While true in principle, I have found that this is not quite so intuitive in practice.
55+
56+
### Using Swift 5 Language Mode In The Swift 6 Compiler
57+
Quick refresher on `Package.swift` files. At the top of every `Package.swift` file, you will see a declaration like this:
58+
59+
```swift
60+
// swift-tools-version:6.0
61+
```
62+
63+
Be advised. Even though this is written as a comment, it is not a comment. It is a directive to the Swift Package Manager. This directive tells the Swift Package Manager the minimum version of the Swift compiler to use. If you have `swift-tools-version:6.0`, then the Swift Package Manager must use the Swift 6 compiler. (We'll see why this is important in a moment.)
64+
65+
To specify the language mode in a target, you can do so like this:
66+
67+
```swift
68+
.target(name: "MyTarget",
69+
dependencies:[.fancyLibrary],
70+
swiftSettings: [
71+
.swiftLanguageMode(.v5)
72+
]
73+
)
74+
```
75+
76+
This tells the Swift 6 compiler to use the Swift 5 language mode for the target `MyTarget`. But according to the docs this should be unnecessary. Remember that the default language mode is Swift 5. So let's leave it out since it is redundant.
77+
78+
```swift
79+
.target(name: "MyTarget",
80+
dependencies:[.fancyLibrary],
81+
swiftSettings: []
82+
)
83+
```
84+
85+
It turns out that we are now using the Swift 6 language mode. Why? According to the docs:
86+
87+
>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`. See [docs](https://arc.net/l/quote/yqrnbxcw).
88+
89+
In other words, the **Swift 5 language mode** is indeed opt-in, but only if you are using `// swift-tools-version:5.10`[^1]. But as soon as you use `// swift-tools-version:6.0`, you are using the Swift 6 language mode, by default. To make matters more confusing when you create a new Swift Package[^2], the Swift Package Manager will default to `// swift-tools-version:6.0`.
90+
91+
[^1]: Or any other version of Swift 5.
92+
[^2]: Using `swift package init` or by clicking **File > New Package** inside Xcode.
93+
94+
### Using `swift-tools-version:5.x` In The Swift 6 Compiler
95+
You are of course allowed to use `swift-tools-version:5.10` and earlier in the Swift 6 compiler, but now there are even more gotchas to be aware of. In particular, the `PackageDescription` API has changed between Swift 5 and Swift 6. This means that you will need to use the Swift 5 version of the `PackageDescription` API.
96+
97+
One of the biggest differences between the two APIs is that in the Swift 5 `PackageDescription` API, **you cannot declare a language mode at a per-target level**. Instead, you must declare the language mode at the package level, meaning all of your targets must use the same language mode. (Per target language mode was introduced in [SE-0435](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0435-swiftpm-per-target-swift-language-version-setting.md) and there doesn't appear to be a way to use this feature in Swift 5 with an upcoming feature flag.)
98+
99+
So in short, while it may be technically true that the Swift 6 language mode is opt-in, this isn't really accurate when it comes to SPM. If you are using `// swift-tools-version:6.0` then the Swift 6 language mode is the default.
100+
101+
## Using Swift 6 Features In Swift 5 Language Mode
102+
Thankfully, both the Swift 5 and Swift 6 compiler allow you to use Swift 6 features. You can even use Swift 6 features when using the Swift 5 language mode! This is done by enabling upcoming features. Be sure to read this official Swift blog post on [Using Upcoming Feature Flags](https://www.swift.org/blog/using-upcoming-feature-flags/).
103+
104+
To enable upcoming features in a Swift Package, define your target like so:
105+
106+
```swift
107+
.target(name: "MyTarget",
108+
dependencies:[.fancyLibrary],
109+
swiftSettings:
110+
[.enableUpcomingFeature("ConciseMagicFile"),
111+
.enableUpcomingFeature("BareSlashRegexLiterals"),
112+
.enableUpcomingFeature("ExistentialAny")])
113+
```
114+
115+
Here is a list of [Swift 6 features](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/sourcecompatibility/) from the Swift 6 documentation. To enable a feature, open the features Swift Evolution proposal (e.g. [SE-0337](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0337-support-incremental-migration-to-concurrency-checking.md)), then look for the **Upcoming Feature Flag**. This is the string that you will be using. Then add it to your target like in the example above. Now you can use Swift 6 features in your Swift 5 code! Even better you can pick and choose which features you are ready to use. This is perfect for incremental migration.
116+
117+
## So Many Options. Which Should I Choose?
118+
While it may be frustrating to encounter these rough edges, it is important to remember that change is good. Strict concurrency checking has the potential to eliminate entire classes of bugs which would be a huge benefit for the whole world.[^3] But it's important to acknowledge that change is also painful. This is hard, and if you are struggling, then that is okay. This is not the first time that Swift has had a difficult transition and it won't be the last.
119+
120+
[^3]: I'm not being hyperbolic here. Concurrency bugs are some of the most difficult to debug and can be some of the most difficult to reproduce. Eliminating these bugs would be a huge positive for society at large.
121+
122+
But thankfully, the Swift 6 compiler gives us a lot of tools to help us through this transition. We can use the Swift 5 language mode to keep our code running while we incrementally adopt Swift 6 features. We can use upcoming feature flags to pick and choose which features we are ready to use. Finally, when we are ready, we can use the Swift 6 language mode to get the full benefits of the new Swift 6 features.
123+
124+
Take full advantage of these tools. They are there to help you. And don't feel like you need to adopt the latest and greatest right now. You should take your time and adopt these features at your own pace.
125+
126+
## Bonus: Easily Enable Upcoming Features Using Static Strings
127+
I like to finish my posts with a little "birthday present" for you. Here is a gist that you can add to any `Package.swift` file. This will allow you to easily enable upcoming features using static strings. Please feel free to fork, clone and contribute the rest of the upcoming feature flags from the [docs](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/sourcecompatibility/).
128+
129+
<script src="https://gist.github.com/DandyLyons/56dc43d0b98befa670758490b43fff07.js"></script>
130+
131+
---
132+
## Recommended Reading
133+
- [Migrating to Swift 6 | Documentation](https://www.swift.org/migration/documentation/migrationguide)
134+
- [Enabling The Swift 6 Language Mode | Documentation](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/swift6mode)
135+
- [Incremental Adoption | Documentation](https://www.swift.org/migration/documentation/swift-6-concurrency-migration-guide/incrementaladoption)
136+
- [Swift.org - Using Upcoming Feature Flags](https://www.swift.org/blog/using-upcoming-feature-flags/)
137+
- [Migrate your app to Swift 6 - WWDC24 - Videos - Apple Developer](https://developer.apple.com/videos/play/wwdc2024/10169/)
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
1+
---
2+
title: 'Safe Constants in GDScript'
3+
slug: safe-constants-in-gdscript
4+
date: 2024-11-19
5+
topics: ["GDScript"]
6+
description:
7+
---
28

39

410
**Research:** https://www.perplexity.ai/search/in-gdscript-i-would-like-a-sol-W8FREhZyQciQcqwrpqUB8g

0 commit comments

Comments
 (0)