1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// RUN: %empty-directory(%t)
// RUN: echo 'main()' >%t/main.swift
// RUN: %target-swiftc_driver -o %t/a.out %s %t/main.swift
// 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
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
}
|