Pattern of type 'E<E<T>>' cannot match 'E<T>'

Given an enum E with an associated generic value T where I implement a ~= overload to match an enum case with a value T, I run into a puzzling compiler error:

enum E<T> {
    case t(T)
}

func ~=<T> (lhs: T, rhs: E<T>) -> Bool {
    switch rhs {
    case .t(lhs): true // ← Pattern of type 'E<E<T>>' cannot match 'E<T>'
    case .t: false
    }
}

Where does this E<T<T>> type come from? Is it because the switch rhs in the ~= refers back to that same implementation of ~=? Adding a where T: Equatable clause makes the error go away.

1 Like

You are missing β€˜let’ in your first pattern. It is wrong syntax as it stands.

switch rhs {
case let .t(value): value == lhs 
}

It is valid syntax. Identifiers not bound with let but present in scope are substituted with their current values for pattern matching. To verify that, you can run this snippet:

let x = 5
let y = 4

switch y {
case x: print("y == x")
default: print("y != x")
}

which prints y != x, because in practice it "desugars" into something semantically equivalent to this:

if x == y { print("y == x") }
else { print("y != x") }

For the match to be valid in the first place, it needs to use the equality operator, which is not available without the where T: Equatable clause. E<T<T>> is likely a red herring here and I would say is a bug in compiler diagnostics.

4 Likes

I wonder what the intended statistic should be.

Huh. Interesting. Thanks for pointing it out. It makes perfect sense, and yet it somehow has never clicked to me and I kept using:

switch y {
case y where y == x: print("a")
default: print("b")
}

I am now not sure which way to use. :slight_smile: