この記事はなに
Swift.orgのブログに投稿されたSwift5.4のリリースについて、個人的に興味深い部分を読んでみました。
アップデート情報
Swift5.4に含まれる新しい言語機能
- 関数、添え字、イニシャライザが複数の可変パラメータをサポート(SE-0284)
- 暗黙的なメンバー構文の拡張(SE-0287)
- リザルトビルダー(SE-0289)
- ローカル関数が、オーバーロードをサポート
- ローカル変数のプロパティラッパー
新しい並列実行モデルでは、識別子としてawait
を修飾せずに使用した場合に、コンパイラは警告と修正を行うようになりました。これらの識別子は、SE-0296の一部としてSwiftの将来のバージョンにおいて、await
キーワードとして解釈されます。
ランタイム性能とコードサイズの改善
Swift5.4では、以前の搜索結果をキャッシュするハッシュテーブルの実装が高速化されたおかげで、実行時のプロトコル適合性チェックが大幅に高速化されました。特に、一般的な実行時のas?
とas!
のキャスト操作が高速化されています。
さらに、連続した配列の変更は、冗長な一意性チェックを回避します。
func foo(_ a: inout [Int]) {
a[0] = 1 // 必須のcopy-on-writeチェックが発生するところ
a[1] = 2 // ここで、余計なCoWチェックは行わない
}
他にも、さまざまなパフォーマンスが改善されました。
- 文字列の補間が、より積極的に定数化
- 特に関数の
inout
引数やwhile
ループにおいて、retain
/release
の呼び出しを削減 - 標準ライブラリのジェネリックなメタデータがコンパイル時に特殊化され、ダーティメモリの使用量が減り、パフォーマンスを向上
コードの補間
大きな関数のボディにおいて、コード補完のパフォーマンスはより速くなりました。
swift-package-managerリポジトリ内の一例では、そのファイルで繰り返される呼び出しは、Swift5.4のself.
のコード補完時間が、Swift5.3と比較して20mから5ms、4倍も速くなっています。
コード補完は、「エラーを含む式」や「文脈が不足している曖昧な式」でも、より信頼できるようになりました。
例を示します。
func test(a: Int, b: String) -> Int { ... }
func test(a: Int, b: Int) -> String { ... }
func test(a: (Int, Int) -> Int) -> Int { ... }
上記のコードに対するコード補完は、以下のように動作するようになりました。
-
test( ... ).prefix(3)
の後にコード補完を呼び出すと、String
のメンバーを示唆します。 -
test(a: 2)
の後にコード補完を実行すると、Int
およびString`のメンバーを示唆します。 - 次のブロックで
$0.
の後にコード補完を実行すると、Int:test { $0. }
のメンバーを示唆します。
型チェッカー
Swift5.4では、a + b + (2 * c)
のような「連結された式」に対する型チェックのパフォーマンスが向上しています。
次のような例を考えてみます。
struct S { var s: String? }
func test(_ a: [S]) {
_ = a.reduce("") {
($0 + "," + ($1.s ?? "")) + ($1.s ?? "") + ($1.s ?? "")
}
}
これまで、このコードの型チェックはタイムアウトになっていましたが、100ミリ秒以内に完了するようになりました。
さらに、他のリテラル式を含む配列リテラルをネストした場合のパフォーマンスも向上しました。
例えば、以下のような無効なコードに対して、以前はコンパイラが「複雑すぎて時間内に解決できない」というメッセージを表示していました。
enum E {
case first
case second
case third
}
let dictionary = [
.first: [0, 1, 2, 3, 4, 5, 6, 7],
.second: [8, 9, 10, 11, 12, 13, 14, 15],
.third: [16, 17, 18, 19, 20, 21, 22, 23],
]
Swift5.4では、このコードが無効であると診断され、正確なエラーメッセージを表示するようになりました。
error: reference to member 'first' cannot be resolved without a contextual type
.first : [ 0, 1, 2, 3, 4, 5, 6, 7],
^
error: reference to member 'second' cannot be resolved without a contextual type
.second : [ 8, 9, 10, 11, 12, 13, 14, 15],
^
error: reference to member 'third' cannot be resolved without a contextual type
.third : [16, 17, 18, 19, 20, 21, 22, 23],
^
型チェッカーは、無効なステートメント(無効なreturn
ステートメントなど)、無効な宣言の参照、パターンマッチのエラーなど、リザルトビルダーの診断機能が向上しました。
例えば、以下のようなものです。
import SwiftUI
struct ContentView: View {
@State private var condition = false
var body: some View {
Group {
if condition {
Text("Hello, World!")
.frame(width: 300)
} else {
return Text("Hello, World!")
}
}
}
}
このコードの場合、型チェッカーは次のようなエラーと同時に、リザルトビルダーを適用するためにreturn
を削除する修正案も報告します。
error: cannot use explicit 'return' statement in the body of result builder 'SceneBuilder'
return Text("Hello, World!")
^