Swift 4.1, available in Xcode 9.3, brings a number of improvements to the language, including automatic implementation of the Equatable and Hashable protocols, conditional conformance, and more.
Conditional conformance
Conditional conformance allows the expression of the idea that a generic type will conform to a protocol only if its type parameters satisfy certain requirements. For example an Array can implement the Equatable protocol only if its elements also conform to it, which can be expressed in the following declaration:
extension Array: Equatable where Element: Equatable {
static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool { ... }
}
This closes a gap in Swift generics, fully enabling the possibility of generic adapter types, i.e., generic types that reflect the capabilities of the composing types. For example, in Swift 3 there exist four different generic types that handle "lazy" items: LazySequence, LazyCollection, LazyBidirectionalCollection, and LazyRandomAccessCollection. Each of those types reimplements, or forwards, the same API as the composing type. Using conditional conformance, a Sequence of a lazy type can be declared as conforming to the lazy protocol without defining any intermediate generic types.
Synthesized == and hashValue
The Swift 4.1 compiler is able to synthesize the implementation of the == and hashValue methods for structs and enums that declare conformance to the Equatable and Hashable protocols. Previously, developers had to provide a custom implementation of those methods, which was a rather tedious task: the == method implementation had, in the general case, to compare each corresponding member of the structs or unions, while the hashValue had to somehow ensure that it returned a unique string. In Swift 4.1, developers can just declare conformance to those protocols and the relevant methods will be automatically synthesized, provided all stored properties or enum cases conform to Equatable or Hashable respectively.
Other significant changes in Swift 4.1 are the following:
-
Index types for most library collections conform now to
Hashableand can be used in key-path subscripts and hashed collections:let s = "Hashable" let p = \String.[s.startIndex] s[keyPath: p] // "H" -
Smart KeyPaths are fully implemented. KeyPaths now support subscript, optional chaining, and optional force-unwrapping.
- Keywords
weakandunownedcannot be used anymore for property declaration in protocols. - Similarly to a restriction already existing for classes, Swift structs no longer allow defining an initializer in a different module that directly initialized the struct’s fields. Before accessing struct fields, the struct must have been initialized calling
self.init.
A full list of all changes within Swift 4.1 can be found in the official change log.