Update on SE-0110 and SE-0155

Hi everyone. In the Swift 3 era, several source-breaking proposals had been accepted with the goal of cleaning up and regularizing parts of the language. However, many of them have been stuck in the "Accepted" but not "Implemented" stage for quite a while now, because we never quite got , and the barrier for breaking source compatibility is much higher now than it was in the heady early days of Swift evolution. As such, the Core Team has started going through some of these proposals to record their current implementation status and subset out remaining unimplemented source-breaking changes. To start off, I recently reviewed the implementation status of two proposals:

  • SE-0110, Distinguish between single-tuple and multiple-argument function types
  • SE-0155, Normalize Enum Case Representation

SE-0110 Distinguish between single-tuple and multiple-argument function types

This proposal changed the behavior of functions with multiple arguments from being considered to have one formal argument of tuple type to instead be treated as formally having multiple arguments. This change has been fully implemented as of Swift 5.2; however, the original proposal as reviewed did not include the special-case conversion from (T, U, ...) -> V to ((T, U, ...)) -> V for function arguments. In response to community feedback, this conversion was added as part of the Core Team's acceptance of the proposal. I have updated the proposal text to include this special case conversion, and changed the proposal status to "Implemented". At the time of acceptance, the Core Team had noted that we "will revisit the design in this area post-Swift 4". If and when that happens, it will be done as a fresh pitch and proposal.

SE-0155 Normalize Enum Case Representation

This proposal changes the behavior of enum case declarations to make their behavior more uniform with function and property declarations. Similar to what SE-0110 established for function types, SE-0155 makes an enum with a compound associated value like case foo(bar: Int, bas: Int) be treated as having multiple formal arguments instead of one tuple payload, with the argument labels becoming part of the case's formal name and the arguments themselves supporting default arguments and the other functionality of function declarations. As of Swift 5.2, the declaration and case construction functionality has been mostly implemented; case declarations can be declared with a common base name but different argument labels, can have default arguments, and can be applied and referenced like labeled function declarations. However, there are outstanding bugs when trying to actually use an enum with multiple cases that share a base name:

https://bugs.swift.org/browse/SR-12206: Symbol collision when multiple enum cases with same base name have default arguments
https://bugs.swift.org/browse/SR-12229: Assertion failure when trying to pattern match enum cases with same base name

Furthermore, none of the proposal's changes to pattern matching behavior have been implemented. Patterns are still allowed to match a compound associated value as a single tuple, and arbitrarily drop or include argument labels:

enum Foo { case foo(bar: Int, bas: Int) }

switch foo {
case .foo(let all): // still accepted
case .foo(bar: let x, let y): // still accepted
case .foo(let x, bas: let y): // still accepted

Although unfortunate, the Core Team does not consider it worth breaking source compatibility to change this behavior. Therefore, the pattern matching part of the proposal has been downscoped to allow for disambiguation when multiple cases share a base name, without changing the behavior for existing enums supported today. The remaining missing functionality should be implementable without breaking source or ABI compatibility. Because of the incomplete implementation, I have left the revised proposal in the "Accepted" state with the two bug reports above attached. If any implementation work does end up requiring breaking source compatibility, or if we decide to pursue other source-breaking changes to enum declaration or pattern matching behavior, we should do so in new proposals.


So it should be Implemented on Swift (5.2), because it only states Implemented on Swift on GitHub SE0110?

Now sorting in GitHub.io for Swift 5.3 will filter this out.

For SE-0155: An attribute on the enum could opt in to strict matching (maybe @strictmatching enum ...). I could see bugs resulting from dropping down to tuple-like matching in some use cases. I could also see that implicit conversion to tuples during matching may be good in other cases. I think it would be nice if we could have it both ways using an attribute.