Swift Digest
Blog | Swift.org Blog↗

Swift 6.4 でやってくる Embedded Swift の改善

Embedded Swift Improvements Coming in Swift 6.4

このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。

この記事の要点

言語の改善

existential(any)型の一般化

これまで Embedded Swift は、AnyObject 制約を持つ existential(any)型しかサポートしていませんでした。つまり、クラスのインスタンスに対してしか使えませんでした。Swift 6.4 では、Any 自体を含めてすべての any 型が使えるようになります。

protocol P {
  func method()
}

extension Int: P {
  func method() { print("\(self) is here") }
}

let a: any P = 17
a.method() // prints "17 is here"

ただし、Embedded Swift のジェネリクスのコンパイルモデルは、すべてのジェネリック関数・型が最終的に特殊化されることを前提とします。このため any 型の使い方には制約があり、any 型の値に対してジェネリック関数を呼び出すことはできません。

extension P {
  func genericMethod<T: P>(_ other: T) { ... }
}

let a: any P = 17
a.genericMethod(a) // error: cannot use generic instance method 'genericMethod' on a value of type 'any P' in Embedded Swift

untyped throws

これまで Embedded Swift では、次のように具体的なエラー型を指定する typed throws しか使えませんでした。

func parseRecord() throws(ParsingError) -> Record { ... }

任意の Error 適合値を throw できる「untyped」な throws は、これまで Embedded Swift では禁止されていました。

func loadImage() throws -> Image { ... } // これまで Embedded Swift では不可

untyped throws は、実質的に any Error 型の値を throw することと同じです。any 型の一般化により、Embedded Swift でも untyped throws が完全にサポートされます。ただし any Error の値を throw するには通常ヒープ割り当てが必要になるため、ヒープ割り当てを避けたいコードでは引き続き typed throws を優先すべきです。

メタタイプ

Embedded Swift では、メタタイプ(Int.self など)はごく限られた場所でしか使えませんでした。たとえば、ジェネリック関数の引数の型を指定する用途です。

rawPointer.bindMemory(to: Value.self, capacity: 1)

Swift 6.4 は、Embedded Swift でメタタイプを完全にサポートします。メタタイプのインスタンスを生成・利用でき、any (DefaultInitializable.Type) のような existential 型も扱えます。次の例は、通常の Swift と同じように動作します。

protocol DefaultInitializable {
  init()
}

extension Int: DefaultInitializable { }

let factory: any (DefaultInitializable.Type) = Int.self
let aValue: any DefaultInitializable = factory.init()

ライブラリの改善

浮動小数点数のパース

Swift では、文字列から浮動小数点数の値をパースできます。

let inputText: String = getInputText()
if let value = Double(inputText) {
  // value は Double
}

この機能を Swift で再実装した結果、これらの浮動小数点数のパース API が Embedded Swift でも使えるようになりました。

並行処理のエラーハンドリング

Embedded Swift の並行処理ライブラリが、throw する操作(throw するタスクやタスクグループなど)をサポートするようになりました。

let task = Task {
  if badThing {
    throw MyError.badThingHappened
  }

  return "ok"
}

print(try await task.value)

試してみる

これらの機能は、Swift development snapshot で今すぐ試せます。始めるには、さまざまなハードウェア上で Embedded Swift をビルド・実行できるサンプルプロジェクトを集めた Swift Embedded Examples リポジトリから入るのがおすすめです。

関連リンク