「Swift 6モード」とは?
Swift 6は2023年にはリリースされません。それはSwift Language WorkgroupのDoug Gregorが明言しています。しかし、AppleがすでにSwift 6の一部をSwift 5.8に同梱していることをご存知でしたか?そうなんです。数週間前にXcode 14.3とともにリリースされたSwiftの一部の機能はデフォルトでオフになっています。Swift 6がリリースされると有効になりますが、それはまだ1年以上先かもしれません。
これらの機能は、既知のAPIのリネーム、動作の調整、コンパイラへの新しい安全性チェックの追加など、Swiftに破壊的変更をもたらします。しかし、いずれはすべて有効になり、コードベースの改善に役立ちます。そして、これらの変更に対応してプロジェクトを更新する必要があります。
すべての機能をプロジェクトで有効にして、コードベースにとって把握すべき破壊的変更がないか確認するのは良いアイデアだと考えました。もちろん、BareSlashRegexLiteralsのように、簡潔なRegex初期化のための/.../正規表現リテラル構文が使えるようになるなど、新機能を活用することもできます。
ありがたいことに、Swift 5.8ではこれらのオプションを有効にする統一的な方法が用意されています。Xcodeのプロジェクトビルド設定にあるOTHER_SWIFT_FLAGSで-enable-upcoming-featureをSwiftに渡すだけです。ただし、利用可能な機能が何かも知る必要がありますが、良い一覧が見つかりませんでした(まだ)。この統一オプションを導入したプロポーザルにはリストが含まれていますが、後から追加される新しいオプション(SE-0384のものなど)では更新されません。では、サポートされているすべてのオプションの信頼できるリストはどこで入手できるのでしょうか?
UPDATE:Swift.orgで直接upcoming flagsでフィルタできるようになりました。
Swiftはオープンソースなので、最も信頼できる場所はSwiftのGitHubリポジトリです!Features.defファイルに、関連するSwift Evolutionプロポーザル番号と有効化されるSwiftバージョンの両方を含むUPCOMING_FEATUREという名前のエントリが含まれています(release/5.8ブランチへのリンク):
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
UPCOMING_FEATURE(ForwardTrailingClosures, 286, 6)
UPCOMING_FEATURE(BareSlashRegexLiterals, 354, 6)
UPCOMING_FEATURE(ExistentialAny, 335, 6)各オプションの簡単な説明は以下の通りです:
ConciseMagicFile:#fileの意味を#filePathではなく#fileIDに変更します。ForwardTrailingClosures: 後方スキャンマッチングルールを廃止します。ExistentialAny: 存在型にanyを要求するようになります。BareSlashRegexLiterals:/.../正規表現リテラル構文を利用可能にします。
なぜかリストに記載されていない2つのオプションがあるようです(調査中):
StrictConcurrency: 完全なConcurrencyチェックを実行します。ImplicitOpenExistentials: 追加のケースで暗黙的なオープンを実行します。
後のバージョンで追加されるオプションもあります(例:ImportObjcForwardDeclarations)。
適切なConcurrencyサポートのためにコードをチェックするため、-warn-concurrency(実際に動作するならStrictConcurrencyと同等のはず)と-enable-actor-data-race-checksも追加で渡すことにしました。
プロジェクトの移行
私と同じように5.8のすべてのオプションを有効にしたい場合は、以下のテキストブロックをコピー(Cmd+C)してから、Xcodeプロジェクトの「Build Settings」タブで「Other Swift Flags」を検索し、そのオプションをエディタで選択してペースト(Cmd+V)してください:
//:configuration = Debug
OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks
//:configuration = Release
OTHER_SWIFT_FLAGS = -enable-upcoming-feature BareSlashRegexLiterals -enable-upcoming-feature ConciseMagicFile -enable-upcoming-feature ExistentialAny -enable-upcoming-feature ForwardTrailingClosures -enable-upcoming-feature ImplicitOpenExistentials -enable-upcoming-feature StrictConcurrency -warn-concurrency -enable-actor-data-race-checks
//:completeSettings = some
OTHER_SWIFT_FLAGS
私のようにSwiftPMでモジュール化されたアプリを使っている場合や、Swiftパッケージで作業している場合は、各ターゲットのswiftSettingsに.enableUpcomingFeatureの配列を追加する必要があります:
let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("BareSlashRegexLiterals"),
.enableUpcomingFeature("ConciseMagicFile"),
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("ForwardTrailingClosures"),
.enableUpcomingFeature("ImplicitOpenExistentials"),
.enableUpcomingFeature("StrictConcurrency"),
.unsafeFlags(["-warn-concurrency", "-enable-actor-data-race-checks"]),
]
let package = Package(
// ...
targets: [
// ...
.target(
name: "MyTarget",
dependencies: [/* ... */],
swiftSettings: swiftSettings
),
// ...
]ファイル先頭のtools versionを5.8にアップグレードするのも忘れないでください:
// swift-tools-version:5.8.enableUpcomingFeatureはSwift 5.8以降でのみ利用可能
これは、プロジェクトターゲットで指定したオプションをSwiftがインポートしたモジュールに自動的に渡さないためです。これは実は良いニュースです。プロジェクトに含めているSwiftパッケージの調整が不要で、自分のアプリコードだけでこれらの機能を使えるからです。逆もまた然りで、パッケージ作者がプロジェクトでこれらの機能を有効にしても、そのパッケージを利用しているプロジェクトのコードには影響しません。
これらを有効にしてビルドしたところ、4種類の問題に遭遇しました:
複数の箇所で
anyキーワードを追加する必要がありました。XcodeがFix-Itで支援してくれました:


なぜか
.sheetモディファイアを持つビューで大量のエラーが発生しました。エラーペアには「Generic parameter ‘Content’ could not be inferred」と「Missing argument for parameter ‘content’ in call」と表示されましたが、あまり参考になりませんでした。まず.sheetのコンテンツを単なるTextビューに置き換えてみましたが解決しませんでした。そこでオプションを1つずつオフにしていったところ、ForwardTrailingClosuresをオフにした時にエラーが消えたため、このオプションはオフのままにしました。将来のSwiftバージョンでより良いエラーメッセージが生成されることを期待して、その時に修正するつもりです。急ぐ必要はありません。Swift 5.9で再試行できます。今は調査する時間がありませんでした。

TCAの
WithViewStoreを返す一部の関数に@MainActorアトリビュートを付ける必要がありましたが、ここでもXcodeがFix-Itで支援してくれました。

多くの箇所で「Non-sendable type ‘…’ passed in call to main actor-isolated function cannot cross actor boundary」という警告が表示されました。そのため、これらの型を
Sendableプロトコルに準拠させました(Sendableについてこちらで学べます)。
自分のアプリRemafoX(約35,000行のSwiftコード)では、それ以外は問題なくビルドできました。プロセス全体にかかった時間は3時間未満でした。
これでプロジェクトはSwiftの未来に備えられました。新しいRegexリテラル機能(let regex = /.*@.*/)も使えます。また、後でSwift 6に移行する必要のある新しいコードを書いてしまうこともありません。すぐにエラーが出るからです。
あなたのプロジェクトはいかがですか?どのupcoming featureに移行したいですか?

