Pattern matching for enums with same base case and distinct associated values


(Martin R) #1

(This question is motivated by a recent question on Stack Overflow.)

As I understand it from SE-0155 Normalize Enum Case Representation, enumeration cases with the same base name are allowed if the argument labels of the associated values are distinct. Case pattern use the argument labels to disambiguate between the cases.

However, this switch statement does not compile:

enum Foo {
    case a(dbl: Double)
    case a(int: Int)
}

func footest(foo: Foo) {
    switch foo {
    case .a(dbl: let x): print("Double", x) // Tuple pattern element label 'dbl' must be 'int'
    case .a(int: let n): print("Int", n)
    }
}

Also – according to the corresponding rationale – a case pattern may omit the labels if there is only one case with the same base name and arity.

But this causes compiler warnings, unexpected results, and runtime crashes:

enum Bar {
    case a(int: Int)
    case a(d1: Double, d2: Double)
}

func bartest(bar: Bar) {
    switch bar {
    case .a(let n): print("Int", n)
    case .a(let d1, let d2): print("Double", d1, d2) // Case is already handled by previous patterns; consider removing it
    }
}

bartest(bar: .a(d1: 1.0, d2: 2.0)) // Int (d1: 1.0, d2: 2.0)
bartest(bar: .a(int: 12)) // Fatal error: unexpected enum case while switching on value of type 'Bar'

Am I completely misunderstanding SE-0155?


(Martin R) #2

Looking at SE-0155 again, I now see that it is marked as accepted, but not as implemented. Also SR-4691 is still β€œin progress.”

Sorry for the noise.