LoginSignup
2
3

More than 3 years have passed since last update.

Swift5.4リリース

Last updated at Posted at 2021-05-09

この記事はなに

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!")
 ^
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3