Comparing enums without their associated values

It is possible:

private enum Foo {
  case foo(value: Int)
  case foo(val: String)
}

In such situation it is good question are these two cases equal without their associated values.
In general way I suppose it is not correct to assume they are equal.

It’s possible to define them but unfortunately they don’t work properly yet - [SR-10077] Switching over duplicate enum case names won't compile · Issue #52479 · swiftlang/swift · GitHub

1 Like

This is what the @CasePathable macro does (and more):

@CasePathable
enum Foo {
  case bar(Int)
  case baz(String)
}

let foo = Foo.bar(42)
foo.is(\.bar)  // true
foo.is(\.baz)  // false
3 Likes

Sure, but you can not only define them, you can create instances. This problem id about switching such a enum, but instances can be passed around.

We should firstly decide the final direction whether we allow cases with equal names or not. This decisicion affects the solution for comparing two enum instances.

It is said in 0155-normalize-enum-case-representation:
Enum cases should have distinct full names. Therefore, shared base name will be allowed:

enum SyntaxTree {
    case type(variables: [TypeVariable])
    case type(instantiated: [Type])
    case selector(string: String)
}

Using only the base name in pattern matching for the previous example would be ambiguous and result in a compile error. In this case, the full name must be supplied to disambiguate.

How suggested ~= operator will work?

let a: SyntaxTree = .type(variables: [])
let b: SyntaxTree = .type(instantiated: [])

a ~= b // true or false?

I rarely met such cases in practice. From my own experience I would say this cases are different, so in the example above the answer is false.

To compare such instances we should fully specialize case name if there two cases with the same name. If case name is unique then it can be omitted.

a ~= b // false
 
a ~ = .type(variables:) // true
b ~= .type(instantiated:) // true

let c: SyntaxTree = .selector(string: "")
x ~= .selector // true

However, the rationale for cases with the same name is not clear from 0155.
The example above can be rewritten in such way:

enum SyntaxTree {
    case typeVariables(_ variables: [TypeVariable])
    case typeInstantiated(_ instantiated: [Type])
    case selector(string: String)
}

My own opinion is that cases with same name are more a problem than a solution and therefore should be restricted (even if compiler will still technically be able process them)

1 Like

I think it is reasonable to simply not support enums that have ambiguous base case names and produce an error at compile time.

I have done this in personal projects with macros already and it worked great.

Fully agree here. Eliminating this ambiguity makes things simpler. Having this feature builtin like Hashable or Codable will be a great win.