-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathattr_implements_fp.swift
153 lines (132 loc) · 4.38 KB
/
attr_implements_fp.swift
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
}