Swift 5.4 Released!

Swift 5.4 is now officially released! This release contains a variety of language and tooling improvements.

You can try out some of the new features in this playground put together by Paul Hudson.

An updated version of The Swift Programming Language for Swift 5.4 is now available on Swift.org. It is also available for free on the Apple Books store.

Language Updates

Swift 5.4 includes the following new language features:

To prepare the way for a new concurrency model, the compiler now emits a warning and fix-it for unqualified uses of await as an identifier. Those identifers will be interpreted as the keyword await in a future version of Swift as part of SE-0296.

Runtime Performance and Code Size Improvements

In Swift 5.4, protocol conformance checks at runtime are significantly faster, thanks to a faster hash table implementation for caching previous lookup results. In particular, this speeds up common runtime as? and as! casting operations.

Further, consecutive array modifications now avoid redundant uniqueness checks.

func foo(_ a: inout [Int]) {
  // Must do copy-on-write (CoW) check here.
  a[0] = 1
  // The compiler no longer generates
  // a redundant CoW check here.
  a[1] = 2
}

Finally, there are a variety of performance improvements:

Swift Package Manager Updates

The Swift Package Manager has several important updates in Swift 5.4:

Windows Platform Support

Support for Swift on Windows has progressed in several important ways:

Developer Experience Improvements

Build Performance

Code Completion

Code completion’s performance is now much faster within large function bodies. In one example within the swift-package-manager repository, code completion time for self. in Swift 5.4 is now 4 times faster (20ms → 5ms) than Swift 5.3, for repeated invocations in that file.

Code completion is also now more reliable in expressions that contain errors, and in expressions that are ambiguous without additional context. For example, given:

func test(a: Int, b: String) -> Int { ... }
func test(a: Int, b: Int) -> String { ... }
func test(a: (Int, Int) -> Int) -> Int { ... }

For the above code, code completion now has the following behavior:

Type Checker

Swift 5.4 improves type checking performance for “linked” expressions such as a + b + (2 * c) For example, consider:

struct S { var s: String? }

func test(_ a: [S]) {
   _ = a.reduce("") {
     ($0 + "," + ($1.s ?? "")) + ($1.s ?? "") + ($1.s ?? "")
   }
}

For this code, the type checker completes in under 100 ms, where previously it would time out.

In addition, the type checker has improved performance for nested array literals that contain other literal expressions. For example, the following invalid code would have previously produced a “too complex to solve in reasonable time” message from the compiler:

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

The Swift 5.4 code now diagnoses this code as invalid with precise error messages:

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],
 ^

The type checker now has improved diagnostics for result builders, including invalid statements (e.g. invalid return statement), referencing invalid declarations, and pattern matching errors. For example:

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!")
      }
    }
  }
}

For this code, the type checker will report the following error, along with a Fix-It to remove return to apply the result builder:

error: cannot use explicit 'return' statement in the body of result builder 'SceneBuilder'
 return Text("Hello, World!")
 ^

Debugging

When debugging Swift code on Apple platforms, variables with resilient types (including Foundation value types such as URL, URLComponents, Notification, IndexPath, Decimal, Data, Date, Global, Measurement, and UUID) are displayed in the Xcode variable view and the frame variable / v command again.