Ambiguous operator in Swift 6.1

This extension works in Swift 6.0 and earlier, but I get an error when I use Swift 6.1 in Xcode 16.3 beta 2: "Ambiguous use of operator '>'"

extension Sequence {
  func sorted<T: Comparable>(
    by keyPath: KeyPath<Element, T>,
    ascending: Bool = true
  ) -> [Element] {
    let compareOp: (T, T) -> Bool = ascending ? (<) : (>)
    return sorted { a, b in
      compareOp(a[keyPath: keyPath], b[keyPath: keyPath])
    }
  }
}

Not too hard to get around the error, but I'm wondering if there was a change to the language that I missed that makes this invalid now?

2 Likes
  1. I don't know what the problem is.

  2. Your quick fix is to not use a ternary operator.

let compareOp: (T, _) -> _ = if ascending { (<) } else { (>) }
  1. Your function is not very versatile. You should not require key paths.
let unsorted = [3, 0, 1, 2, -1]
let sorted = Array(-1...3)
#expect(unsorted.sorted(by: \.self) == sorted)
#expect(unsorted.sorted(by: \.self, >) == sorted.reversed())

let unsortedTuples = [(1, 1), (0, 1), (1, 0), (0, 0)]
let sortedTuples = [(0, 1), (0, 0), (1, 1), (1, 0)]
#expect(unsortedTuples.sorted(by: \.self, (<, >)).elementsEqual(sortedTuples, by: ==))
public extension Sequence {
  @inlinable func sorted<Comparable: Swift.Comparable, Error>(
    by comparable: (Element) throws(Error) -> Comparable
  ) throws(Error) -> [Element] {
    try sorted(by: comparable, <)
  }

  @inlinable func sorted<each Comparable: Swift.Comparable, Error>(
    by comparable: (Element) throws(Error) -> (repeat each Comparable),
    _ areInIncreasingOrder: (repeat (each Comparable, each Comparable) throws(Error) -> Bool)
  ) throws(Error) -> [Element] {
    do {
      return try sorted {
        for (comparables, areInIncreasingOrder) in
              repeat try ((each comparable($0), each comparable($1)), each areInIncreasingOrder) {
          if try areInIncreasingOrder(comparables.0, comparables.1) { return true }
          if try areInIncreasingOrder(comparables.1, comparables.0) { return false }
        }
        return false // Equality.
      }
    } catch { throw error as! Error }
  }
}