Pattern matching similar enum cases seems broken

This feels like a language bug but it's possible I'm just holding it wrong. I'm able to construct an enum like the following:

enum Thing {
  case thing(Int)
  case thing(Int, Int)
  case thing(Int, also: String)
}

The compiler doesn't complain and the cases seem very independent to me. However it seems to be impossible to pattern match against it. Any attempt gets complains about accessing enums as tuples, exhaustiveness checking, and redundant cases.

enum Thing {
  case thing(Int)
  case thing(Int, Int)
  case thing(Int, also: String)

  var thing: Bool {
    switch self {
      case .thing(let a):
        return a == 0
      case .thing(let a, let b):
        return a == b
      case .thing(let a, also: let str):
        return a == (Int(str) ?? 0)
    }
  }
}

If it's impossible to use an enum then surely it shouldn't be able to compile in the first place?

4 Likes

Check out this bug, it seems to be what you're encountering: [SR-10077] Switching over duplicate enum case names won't compile · Issue #52479 · apple/swift · GitHub

(But you really should give the enum cases different [descriptive] names... Anything else literally obscures the intent when you have to construct Things somewhere else)

Naturally, in almost all cases different names would be more readable. But it shouldn't be up to the compiler to determine whether or not the programmers choice of identifiers is in bad taste. ;)

Case name overloading was specifically added to Swift to enable the additional uses cases provided by the feature. However, the feature has never worked correctly. You can sort of avoid the issue by using default associated values, but that doesn't enable overloads with unique values.

2 Likes

Here's, I think, the relevant core team message on the topic: