Swift 5.8 includes a small change to documentation as sorting algorithm is guaranteed to be stable (already implemeneted before Swift 5) and following features:
Explicit self
has historically been required in closures, in order to help prevent users from inadvertently creating retain cycles. As of Swift 5.3, implicit self
is permitted in closures when self
is written explicitly in the capture list.
Swift 5.8 extends this support to weak self
captures, and permit implicit self
as long as self
has been unwrapped.
class FooViewController {
let button: Button
func dismiss() {}
func setup() {
button.tapHandler = { [weak self] in
guard let self else { return }
dismiss()
}
}
}
Like with implicit self
for strong
and unowned
captures, the compiler will synthesize an implicit self.
for calls to properties / methods on self
inside a closure that uses weak self
.
Swift 5.8 introduces two related changes to make it easier to adopt new attributes in existing code:
#if
checks to surround attributes on a declaration wherever they appear, eliminating the need to clone a declaration just to adopt a new attribute.hasAttribute(AttributeName)
that evalutes true
when the compiler has support for the attribute with the name AttributeName in the current language mode.#if hasAttribute(preconcurrency)
@preconcurrency
#endif
protocol P: Sendable {
func f()
func g()
}
Conditional directive hasAttribute
only considers attributes that are part of the language, custom attributes (property wrappers, result builders, and global actors) will evaluate false
.
A conditionally-compiled branch based on #if hasAttribute(UnknownAttributeName)
can still be parsed by an existing compiler, even though it will not be applied to the declaration because it isn’t understood.
The compiler flag -enable-upcoming-feature X
can now be used to enable a specific feature X
that has been accepted by the evolution process, but whose introduction into the language is waiting for the next major version (e.g., version 6).
Types outside of the standard library which conform to ExpressibleByIntegerLiteral are restricted in practice in how large of a literal value they can be built with, because the value passed to init(integerLiteral:) must be of a type supported by the standard library.
Swift 5.8 adds a new type to the standard library called StaticBigInt
which is capable of expressing any integer value. This can be used as the associated type of an ExpressibleByIntegerLiteral conformance.
extension UInt256: ExpressibleByIntegerLiteral {
public init(integerLiteral value: StaticBigInt) {
precondition(
value.signum() >= 0 && value.bitWidth <= Self.bitWidth + 1,
"integer literal '\(value)' overflows when stored into '\(Self.self)'"
)
self.words = Words()
for wordIndex in 0..<Words.count {
self.words[wordIndex] = value[wordIndex]
}
}
}
Currently, passing a keypath to print(), yields the standard output for a Swift class. This is not very useful.
struct Theme {
var backgroundColor: Color
var foregroundColor: Color
var overlay: Color {
backgroundColor.withAlpha(0.8)
}
}
print(\Theme.backgroundColor)
would have an output of roughly Swift.KeyPath<Theme, Color>
, which doesn’t allow foregroundColor
to be distinguished from any other property on Theme
.
Swift 5.8 takes advantage of whatever information is available in the binary to implement the debugDescription requirement of CustomDebugStringConvertible
.
print(\Theme.backgroundColor) // outputs "\Theme.<offset 0 (Color)>"
print(\Theme.overlay) // outputs \Theme.<computed 0xABCDEFG (Color)>
Swift 5.8 rounds out initialization functionality for every relevant member of UnsafeMutablePointer
family:
UnsafeMutablePointer
UnsafeMutableRawPointer
UnsafeMutableBufferPointer
UnsafeMutableRawBufferPointer
Slice<UnsafeMutableBufferPointer>
Slice<UnsafeMutableRawBufferPointer>
The functionality will allow managing initialization state in a much greater variety of situations, including easier handling of partially-initialized buffers.