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

Adrian Zubarev adrian.zubarev at devandartist.com
Thu Feb 2 07:42:01 CST 2017

Great, thanks. Love it :)


Adrian Zubarev
Sent with Airmail

Am 2. Februar 2017 um 14:39:43, Daniel Duan (daniel at duan.org) schrieb:

This has been answered in various forms in the thread. Short answer: yes.

On Feb 2, 2017, at 2:05 AM, Adrian Zubarev <adrian.zubarev at devandartist.com> wrote:

Is that correct that this proposal will add some sort of overloading enum cases by different labels?

enum Foo {
    case foo(a: Int)
    case foo(a: Int, b: Int)
Is Foo a valid enum after this proposal?

Adrian Zubarev
Sent with Airmail

Am 19. Januar 2017 um 19:37:50, Daniel Duan via swift-evolution (swift-evolution at swift.org) schrieb:

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)

## 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.

swift-evolution mailing list
swift-evolution at swift.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170202/721a091d/attachment.html>

More information about the swift-evolution mailing list