blob: 21096fc433339c9c5cb368ef9d03b8a7c921071b [file] [log] [blame]
// 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
}