Prefix and postfix operators not working for tuple types

Are these errors caused by a known compiler bug (in Xcode 10):

infix operator |||
prefix operator <<<
postfix operator >>>

func |||(lhs: (Int, Int), rhs: (Int, Int)) -> Void { print("infix") }
prefix  func <<<(rhs: (Int, Int)) -> Void { print("prefix") }
postfix func >>>(lhs: (Int, Int)) -> Void { print("postfix") }

(1, 2) ||| (3, 4) // Prints "infix"
<<<(1, 2) // ERROR: '<<<' is not a prefix unary operator
(1, 2)>>> // ERROR: '>>>' is not a postfix unary operator

?

Note that all three works as expected when called in "function form":

(|||)((1, 2), (3, 4)) // Prints "infix"
(<<<)((1, 2)) // Prints "prefix"
(>>>)((1, 2)) // Prints "postfix"

Further details here.

All three work if the parameter type is not a tuple type:

infix operator |||
prefix operator <<<
postfix operator >>>

func |||(lhs: Int, rhs: Int) -> Void { print("infix") }
prefix  func <<<(rhs: Int) -> Void { print("prefix") }
postfix func >>>(lhs: Int) -> Void { print("postfix") }

1 ||| 2 // Prints "infix"
<<<3 // Prints "prefix"
4>>> // Prints "postfix"

(1) ||| (2) // Prints "infix"
<<<(3) // Prints "prefix"
(4)>>> // Prints "postfix"

(|||)(1, 2) // Prints "infix"
(<<<)(3) // Prints "prefix"
(>>>)(4) // Prints "postfix"

All three work with any type (including tuple types) if the parameter is generic:

infix operator |||
prefix operator <<<
postfix operator >>>

func |||<T>(lhs: T, rhs: T) -> Void { print("infix") }
prefix  func <<<<T>(rhs: T) -> Void { print("prefix") }
postfix func >>><T>(lhs: T) -> Void { print("postfix") }

1 ||| 2 // Prints "infix"
<<<3 // Prints "prefix"
4>>> // Prints "postfix"

(1, 2) ||| (3, 4) // Prints "infix"
<<<(5, 6) // Prints "prefix"
(7, 8)>>> // Prints "postfix"

Oh, turns out I reported this issue for prefix operators in 2015 : )
SR-294

Any chance of it getting fixed?

4 Likes

I'm having a hard time (fortunately) trying to reproduce this on master. Probably fixed here recently by @Slava_Pestov (see the diff of matching_patterns.swift).

2 Likes

Yeah, I think that fixed it. The old code was written that way because it predates the new parameter list representation. Do you still want to submit a PR with new test cases?

Yes, it's on my queue. You think it's superfluous?

No, quite the opposite, I definitely think we should add the test case. At the time I made the change I knew there was a behavioral difference since I saw the test output changed but I didn't dig deeper and for some reason thought it was just emitting different diagnostics in an invalid case.

1 Like