Swift Digest
SE-0441 | Swift Evolution

Formalize ‘language mode’ terminology

Proposal
SE-0441
Authors
James Dempsey
Review Manager
John McCall
Status
Implemented (Swift 6.1)

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]
)

既存のイニシャライザは @availabledeprecated / renamed で非推奨となり、コンパイラが fix-it を提示します。

2. Package.swiftLanguageVersions プロパティの改名

Package の stored property swiftLanguageVersionsswiftLanguageModes に改名されます。後方互換性のために、swiftLanguageVersionsswiftLanguageModes にアクセスする computed property として残りますが、swift-tools-version 6.0 以上では非推奨扱いとなり、fix-it で swiftLanguageModes への置き換えが提案されます。

3. SwiftVersion 列挙型の改名

SwiftVersionSwiftLanguageMode に改名されます。SwiftVersionSwiftLanguageMode の 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 な見通しであり、本提案で実現を約束するものではありません)。