[swift-evolution] [draft] Compound Names For Enum Cases

Daniel Duan daniel at duan.org
Thu Jan 19 12:37:34 CST 2017

Hi all,

Here’s a short proposal for fixing an inconsistency in Swift’s enum. Please share you feedback :)

(Updating/rendered version: https://github.com/dduan/swift-evolution/blob/compound-names-for-enum-cases/proposals/NNNN-Compound-Names-For-Enum-Cases.md <https://github.com/dduan/swift-evolution/blob/compound-names-for-enum-cases/proposals/NNNN-Compound-Names-For-Enum-Cases.md>)

## Introduction

Argument labels are part of its function's declaration name. An enum case
declares a function that can be used to construct enum values. For cases with
associated values, their labels should be part of the constructor name, similar
to "normal" function and methods. In Swift 3, however, this is not true. This
proposal aim to change that.

## Motivation

After SE-0111, Swift function's fully qualified name consists of its base name
and all argument labels. As a example, one can invoke a function with its
fully name:

func f(x: Int, y: Int) {}

f(x: y:)(0, 0) // Okay, this is equivalent to f(x: 0, y: 0)

This, however, is not true when enum cases with associated value were

enum Foo {
    case bar(x: Int, y: Int)

Foo.bar(x: y:)(0, 0) // Does not compile as of Swift 3

Here, the declared name for the case is `foo`; it has a tuple with two labeled
fields as its associated value. `x` and `y` aren't part of the case name. This
inconsistency may surprise some users.

Using tuple to implement associated value also limits us from certain layout
optimizations as each payload need to be a tuple first, as opposed to simply be
unique to the enum.

## Proposed solution

Include labels in enum case's declaration name. In the last example, `bar`'s
full name would become `bar(x:y:)`, `x` and `y` will no longer be labels in a
tuple. The compiler may also stop using tuple to represent associated values.

## Detailed design

When labels are present in enum cases, they are now part of case's declared name
instead of being labels for fields in a tuple. In details, when constructing an
enum value with the case name, label names must either be supplied in the
argument list it self, or as part of the full name.

Foo.bar(x: 0, y: 0) // Okay, the Swift 3 way.
Foo.bar(x: y:)(0, 0) // Equivalent to the previous line.
Foo.bar(x: y:)(x: 0, y: 0) // This would be an error, however.

Note that since the labels aren't part of a tuple, they no longer participate in
type checking, similar to functions:

let f = Foo.bar // f has type (Int, Int) -> Foo
f(0, 0) // Okay!
f(x: 0, y: 0) // Won't compile.

## Source compatibility

Since type-checking rules on labeled tuple is stricter than that on function
argument labels, existing enum value construction by case name remain valid.
This change is source compatible with Swift 3.

## Effect on ABI stability and resilience

This change introduces compound names for enum cases, which affects their
declaration's name mangling.

The compiler may also choose to change enum payload's representation from tuple.
This may open up more space for improving enum's memory layout.

## Alternatives considered

Keep current behaviors, which means we live with the inconsistency.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170119/7bec57eb/attachment.html>

More information about the swift-evolution mailing list