Last week, Apple announced this year’s WWDC, while Swift is steadily progressing to what’s next after Swift 5.

Starter tasks

  • TF-336 [Python] Add unit testing infrastructure for Python 2 and 3
  • TF-337 [Python] PythonObject conformance to Sequence uses array indexing instead of Python.iter(...)
  • TF-342 [Python] Adopt Python iterator C API
  • TF-351 [AutoDiff] Fixit .withoutDerivative() is inserted to the wrong place

News and community

Chris Lattner and Brennan Saeta gave a talk on Swift for TensorFlow.

SwiftNIO 2 is upon us, having started its convergence. It includes improvements to the public API and comes with a useful migration guide. 🚀

Johannes Weiss shared that swift-log is now available on GitHub.

[..] swift-log is only the start of a logging that works across the whole ecosystem.

Commits and pull requests

After about three years, John Holdsworth merged a pull request implementing SE-0068: Expanding Swift Self to class members and value types! 💪

Eric Eckstein merged a pull request that eliminates memory allocations from code making heavy use of generics, protocols with associated types, conditional conformances and various other language features:

These are temporary allocations made by the Swift runtime, while building type metadata. While in most cases the results are cached and reach a steady state, this will still help startup time. For casts to protocols where the type conditionally conforms, speeds up runtime too.

Accepted proposals

SE-0242: Synthesize default values for the memberwise initializer was accepted.

The proposal is accepted, with a request that the original proposal be amended for clarification of actual behavior. The Core Team felt that the proposal should more explicitly illustrate the actual behavior in a few specific cases, as this was the crux of some of the back-and-forth in the review thread. Note: the proposal has been updated to include more details in the proposed solution section, as requested by the Core Team.

Returned proposals

SE-0245: Add an Array Initializer with Access to Uninitialized Storage was returned for revision as (part of) SE-0223.

This proposal suggests a new initializer for Array and ContiguousArray that provides access to an array’s uninitialized storage buffer.

Some collection operations require working on a fixed-size buffer of uninitialized memory. For example, one O(n) algorithm for performing a stable partition of an array is as follows:

  1. Create a new array the same size as the original array.
  2. Iterate over the original array, copying matching elements to the beginning of the new array and non-matching elements to the end.
  3. When finished iterating, reverse the slice of non-matching elements.

Unfortunately, the standard library provides no way to create an array of a particular size without initializing every element. Even if we avoid initialization by manually allocating the memory using an UnsafeMutableBufferPointer, there’s no way to convert that buffer into an array without copying the contents. There simply isn’t a way to implement this particular algorithm with maximum efficiency in Swift.

Proposals in review

SE-0250: Swift Code Style Guidelines and Formatter is under review.

We propose that the Swift project adopt a set of code style guidelines and provide a formatting tool that lets users easily diagnose and update their code according to those guidelines. These guidelines would not be mandatory for all projects, but encouraged for Swift code to follow for general consistency.

SE-0249: Key Path Expressions as Functions is under review.

This proposal introduces the ability to use the key path expression \Root.value wherever functions of (Root) -> Value are allowed.

SE-0248: String Gaps and Missing APIs is under review.

String and related types are missing trivial and obvious functionality, much of which currently exists internally but has not been made API. We propose adding 9 new methods/properties and 3 new code unit views.

These missing APIs address commonly encountered gaps and missing functionality for users of String and its various types, often leading developers to reinvent the same trivial definitions.

We propose:

  • 6 simple APIs on Unicode’s various encodings
  • 2 generic initializers for string indices and ranges of indices
  • Substring.base, equivalent to Slice.base
  • Make Character.UTF8View and Character.UTF16View public
  • Add Unicode.Scalar.UTF8View

SE-0247: Contiguous Strings is under review.

One of the most common API requests from performance-minded users of string is a way to get direct access to the raw underlying code units. Now that Swift 5 uses UTF-8 for its preferred encoding, we can provide this.

“Contiguous strings” are strings that are capable of providing a pointer and length to validly encoded UTF-8 contents in constant time. Contiguous strings include:

  • All native Swift string forms
  • Lazily bridged Cocoa strings that provide a pointer to contiguous ASCII
  • Any “shared string” concept we may add in the future

SE-0246: Generic Math(s) Functions is under review.

This proposal introduces two new protocols to the standard library: ElementaryFunctions and Real. These protocols combine to provide “basic math functions” in generic contexts for floating-point and SIMD types, and provide a path to extend that functionality to planned complex types in the future.

BinaryFloatingPoint (and the protocols it refines) provides a powerful set of abstractions for writing numerical code, but it does not include the transcendental operations defined by the C math library, which are instead imported by the platform overlay as a set of overloaded concrete free functions.

Swift Forums

Michael Ilseman shared some background information about what is available in String’s ABI in Swift 5.

String’s ABI encodes information for performant processing and future flexibility, allowing the standard library to run faster and producer smaller and more flexible code. But, this information is not available as API for low-level programming as it’s hidden behind the abstraction of the String type. With this information formally part of String’s ABI, we should lift the veil of the String type and start exposing these as API.

Michael Munday shared an update summarizing the implementation of the enum layout.

The issues this post is concerned with affect enums with multiple cases, one or more of which has a payload. In the Swift compiler enums fitting this description are implemented either as a single-payload enum or a multi-payload enum. A single-payload enum consists of exactly one case with a payload as well as one or more empty cases. Multi-payload enums are any other enum with multiple cases and one or more payloads. In particular, multi-payload enums are used whenever there are multiple cases with payloads regardless of whether the payloads have the same type.

Doug Gregor pitched a proposal around Key Path Member Lookup.

Dynamic member lookup allows a type to opt in to extending member lookup (“dot” syntax) for arbitrary member names, turning them into a string that can then be resolved at runtime. Dynamic member lookup allows interoperability with dynamic languages where the members of a particular instance can only be determined at runtime… but no earlier. Dynamic member lookups therefore tend to work with type-erased wrappers around foreign language objects (e.g., PyVal for an arbitrary Python object), which don’t provide much static type information.

[We propose to] introduce a new attribute @keyPathMemberLookup that can be placed on the definition of a type. For such types, “dot” syntax to access a member will be rewritten as a use of a special subscript whose argument is a key path describing the member.

Manolo van Ee wrote a post with thoughts on Opaque Result types.

I’ve been trying to wrap my head around SE-0244: Opaque Result Types and recently I had some realizations that helped me understand the proposal better. I noticed I’m not the only one confused about it, so I thought I’d write down some things that might help others to get a better grasp of the concept as well.

In doing so, I’d also like to try and rebrand opaque result types, or at least the underlying mechanism, to something I’m calling ‘reverse generics’. I think viewing this all from a slightly different perspective helps a lot in understanding the concepts involved.

Tom Doron shared a proposal for a Server Metrics API.

Almost all production server software needs to emit metrics information for observability. The SSWG aims to provide a number of packages that can be shared across the whole Swift Server ecosystem so we need some amount of standardization. Because it’s unlikely that all parties can agree on one full metrics implementation, this proposal is attempting to establish a metrics API that can be implemented by various metrics backends which then post the metrics data to backends like prometheus, graphite, publish over statsd, write to disk, etc.

As outlined above, we should standardize on an API that if well adopted would allow application owners to mix and match libraries from different parties with a consistent metrics collection solution.

Vinicius Vendramini pitched a proposal to introduce custom attributes.

Swift currently supports marking declarations with attributes, such as @objc and @deprecated. The compiler uses these attributes to change the way it interprets the corresponding code. However, there is no support for declaring and using new attributes to suit the needs of a project or library. This proposal aims to change that.

Dan Zheng and Richard Wei pitched a proposal to introduce (static) callables in Swift.

This proposal introduces callables to Swift. Values that behave like functions can take advantage of this syntactic sugar, to look like a function call when they are called.

In a nutshell, we propose to introduce a new declaration syntax with the keyword call:

struct Adder {
    var base: Int
    call(_ x: Int) -> Int {
        return base + x

Values that have a call member can be applied like a function, forwarding arguments to the call member.

let add3 = Adder(base: 3)
add3(10) // => 13


Ever created a “small” memory leak? 🚰