| // RUN: %empty-directory(%t) |
| // RUN: echo 'main()' >%t/main.swift |
| // RUN: %target-swiftc_driver -o %t/a.out %s %t/main.swift -Xfrontend -enable-operator-designated-types -Xfrontend -solver-enable-operator-designated-types |
| // RUN: %target-codesign %t/a.out |
| // RUN: %target-run %t/a.out | %FileCheck %s |
| // REQUIRES: executable_test |
| |
| // This is a more-thorough and explicit test for rdar://43804798 that uses @_implements to |
| // achieve "Comparable Floating Point values are FP-like when known to be FP, Comparable-like |
| // when only known to be comparable". |
| |
| // Could calls to the different comparison operators. |
| public var comparedAsCauxmparablesCount : Int = 0 |
| public var comparedAsFauxtsCount : Int = 0 |
| |
| infix operator .< : ComparisonPrecedence, BinaryFauxtingPoint, Cauxmparable |
| |
| public protocol Cauxmparable { |
| static func .< (lhs: Self, rhs: Self) -> Bool |
| } |
| |
| public protocol FauxtingPoint : Cauxmparable { |
| static var nan: Self { get } |
| static var one: Self { get } |
| static var two: Self { get } |
| } |
| |
| public protocol BinaryFauxtingPoint: FauxtingPoint { |
| @_nonoverride static func .< (lhs: Self, rhs: Self) -> Bool |
| |
| var bitPattern: UInt8 { get } |
| } |
| |
| public extension BinaryFauxtingPoint { |
| // This version of .< will be called in a context that only knows it has a Cauxmparable. |
| @_implements(Cauxmparable, .<(_:_:)) |
| static func _CauxmparableLessThan(_ lhs: Fauxt, _ rhs: Fauxt) -> Bool { |
| print("compared as Cauxmparables") |
| comparedAsCauxmparablesCount += 1 |
| return lhs.bitPattern < rhs.bitPattern |
| } |
| } |
| |
| public enum State { |
| case Nan |
| case One |
| case Two |
| } |
| |
| public struct Fauxt { |
| let state: State |
| init(_ s: State) { |
| state = s |
| } |
| public static var nan: Fauxt { |
| return Fauxt(State.Nan) |
| } |
| public static var one: Fauxt { |
| return Fauxt(State.One) |
| } |
| public static var two: Fauxt { |
| return Fauxt(State.Two) |
| } |
| } |
| |
| extension Fauxt: BinaryFauxtingPoint { |
| // Requirement from BinaryFauxtingPoint |
| public var bitPattern: UInt8 { |
| switch state { |
| case .One: |
| return 1 |
| case .Two: |
| return 2 |
| case .Nan: |
| return 0xff |
| } |
| } |
| } |
| |
| public extension Fauxt { |
| // This version of .< will be called in a context that knows it has a Fauxt. |
| // It is inside an extension of Fauxt rather than the declaration of Fauxt |
| // itself in order to avoid a warning about near-matches with the defaulted |
| // requirement from Cauxmparable..< up above. |
| static func .<(_ lhs: Fauxt, _ rhs: Fauxt) -> Bool { |
| print("compared as Fauxts") |
| comparedAsFauxtsCount += 1 |
| if lhs.state == .Nan || rhs.state == .Nan { |
| return false |
| } else { |
| return lhs.bitPattern < rhs.bitPattern |
| } |
| } |
| } |
| |
| public func compare_Cauxmparables<T:Cauxmparable>(_ x: T, _ y: T) -> Bool { |
| return x .< y |
| } |
| |
| public func compare_FauxtingPoint<T:FauxtingPoint>(_ x: T, _ y: T) -> Bool { |
| return x .< y |
| } |
| |
| public func compare_BinaryFauxtingPoint<T:BinaryFauxtingPoint>(_ x: T, _ y: T) -> Bool { |
| return x .< y |
| } |
| |
| public func compare_Fauxts(_ x: Fauxt, _ y: Fauxt) -> Bool { |
| return x .< y |
| } |
| |
| public func main() { |
| assert(compare_Cauxmparables(Fauxt.one, Fauxt.two)) |
| assert(comparedAsCauxmparablesCount == 1) |
| // CHECK: compared as Cauxmparables |
| assert(compare_Cauxmparables(Fauxt.one, Fauxt.nan)) |
| assert(comparedAsCauxmparablesCount == 2) |
| // CHECK: compared as Cauxmparables |
| assert(!compare_Cauxmparables(Fauxt.nan, Fauxt.one)) |
| assert(comparedAsCauxmparablesCount == 3) |
| // CHECK: compared as Cauxmparables |
| |
| assert(compare_FauxtingPoint(Fauxt.one, Fauxt.two)) |
| assert(comparedAsCauxmparablesCount == 4) |
| // CHECK: compared as Cauxmparables |
| assert(compare_FauxtingPoint(Fauxt.one, Fauxt.nan)) |
| assert(comparedAsCauxmparablesCount == 5) |
| // CHECK: compared as Cauxmparables |
| assert(!compare_FauxtingPoint(Fauxt.nan, Fauxt.one)) |
| assert(comparedAsCauxmparablesCount == 6) |
| // CHECK: compared as Cauxmparables |
| |
| assert(compare_Fauxts(Fauxt.one, Fauxt.two)) |
| assert(comparedAsFauxtsCount == 1) |
| // CHECK: compared as Fauxts |
| assert(!compare_Fauxts(Fauxt.one, Fauxt.nan)) |
| assert(comparedAsFauxtsCount == 2) |
| // CHECK: compared as Fauxts |
| assert(!compare_Fauxts(Fauxt.nan, Fauxt.one)) |
| assert(comparedAsFauxtsCount == 3) |
| // CHECK: compared as Fauxts |
| |
| assert(compare_BinaryFauxtingPoint(Fauxt.one, Fauxt.two)) |
| assert(comparedAsFauxtsCount == 4) |
| // CHECK: compared as Fauxts |
| assert(!compare_BinaryFauxtingPoint(Fauxt.one, Fauxt.nan)) |
| assert(comparedAsFauxtsCount == 5) |
| // CHECK: compared as Fauxts |
| assert(!compare_BinaryFauxtingPoint(Fauxt.nan, Fauxt.one)) |
| assert(comparedAsFauxtsCount == 6) |
| // CHECK: compared as Fauxts |
| |
| } |