Formalize ‘language mode’ terminology
01 何が問題だったのか
Swift には、同じコンパイラで古いバージョンの言語仕様としてビルドするためのモード切り替えの機能があります。たとえば Swift 6 のコンパイラで Swift 5 の挙動のままビルドするといったことができ、これによりツールチェインの更新と言語バージョンの切り替えを分離できます。
この機能は Swift 4 の時点から一貫して「language mode」と呼ばれており、Swift コミュニティで定着した用語です。ところが、実際のツールや API には「language mode」という名前が使われておらず、以下のように「Swift version」という言葉が使われていました。
- Swift コンパイラのオプション
-swift-version - Swift Package Manager の
Packageイニシャライザの引数swiftLanguageVersions: [SwiftVersion]? - 同じく
PackageのプロパティswiftLanguageVersions - 列挙型
SwiftVersion - SE-0435 で追加された
SwiftSetting.swiftLanguageVersion(_:_:)
しかし、「Swift version」はツールチェイン/コンパイラのバージョン(例: Swift 6.0.1)を指す言葉でもあり、language mode を指す用語としても使われていたため、どちらのバージョンの話をしているのかが常に曖昧でした。実際にフォーラムやドキュメントでも混同の原因になっていました。
この提案は、ツールや API の命名を、実態として定着している「language mode」という用語に揃え、この曖昧さを解消することを目的としています。
02 どのように解決されるのか
Swift コンパイラと Swift Package Manager の API を、「language mode」という用語に合わせて改名します。既存の「Swift version」ベースの API は後方互換性のために残しつつ、非推奨(deprecated)として fix-it で新しい名前に誘導されるようにします。
Swift コンパイラのオプション
既存の -swift-version と同じ挙動の -language-mode オプションが追加されます。
swiftc -language-mode 6 main.swift
-swift-version も引き続き動作しますが、コンパイラのヘルプでは -language-mode のみが表示され、-swift-version はトップレベルのヘルプから外れます。オプション名に「Swift」を付けないのは、Swift コンパイラという文脈上 language mode が Swift のものであることが自明だからです。
Swift Package Manager の API
swift-tools-version が 6.0 以上のマニフェストに対して、次の4点の変更が入ります。
1. Package の新しいイニシャライザ
swiftLanguageVersions: [SwiftVersion]? の代わりに swiftLanguageModes: [SwiftLanguageMode]? を取るイニシャライザが追加されます。
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "MyLibrary",
products: [
.library(name: "MyLibrary", targets: ["MyLibrary"]),
],
targets: [
.target(name: "MyLibrary"),
],
swiftLanguageModes: [.v5, .v6]
)
既存のイニシャライザは @available の deprecated / renamed で非推奨となり、コンパイラが fix-it を提示します。
2. Package.swiftLanguageVersions プロパティの改名
Package の stored property swiftLanguageVersions が swiftLanguageModes に改名されます。後方互換性のために、swiftLanguageVersions は swiftLanguageModes にアクセスする computed property として残りますが、swift-tools-version 6.0 以上では非推奨扱いとなり、fix-it で swiftLanguageModes への置き換えが提案されます。
3. SwiftVersion 列挙型の改名
SwiftVersion が SwiftLanguageMode に改名されます。SwiftVersion は SwiftLanguageMode の type alias として残りますが、6.0 で非推奨となります。
// 新しい書き方
swiftLanguageModes: [SwiftLanguageMode] = [.v5, .v6]
4. SwiftSetting への swiftLanguageMode(_:_:) の追加
SE-0435 で導入されたターゲットごとの language mode 指定 API SwiftSetting.swiftLanguageVersion(_:_:) は、swiftLanguageMode(_:_:) に置き換えられます。
.target(
name: "MyLibrary",
swiftSettings: [
.swiftLanguageMode(.v6),
]
)
古い swiftLanguageVersion(_:_:) も renamed 指定で残り、fix-it により新しい API に誘導されます。関数名を languageMode ではなく swiftLanguageMode としているのは、SwiftPM のマニフェストでは C や C++ などの他言語の設定(cLanguageStandard など)と並ぶため、言語名を接頭辞として付ける既存の慣例に揃えるためです。
今後の見通し(Future Directions)
当初の提案には、#if などで使えるコンパイル条件 languageMode() の追加も含まれていましたが、本提案ではツールと API の用語整理に範囲を絞り、言語自体への追加は別提案として切り出されています(speculative な見通しであり、本提案で実現を約束するものではありません)。