Skip to content

Commit 8a072e6

Browse files
committed
[SR-8961] Testcase for more-involved use of @_implements using @_nonoverride.
1 parent 77280b0 commit 8a072e6

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

test/attr/attr_implements_fp2.swift

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: echo 'main()' >%t/main.swift
3+
// RUN: %target-swiftc_driver -o %t/a.out %s %t/main.swift
4+
// RUN: %target-codesign %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s
6+
// REQUIRES: executable_test
7+
8+
// This is a yet-more-thorough test for rdar://43804798 (and its successor rdar://45183426) that
9+
// uses @_implements to achieve "Comparable Floating Point values are FP-like when known to be FP,
10+
// Comparable-like when only known to be comparable".
11+
//
12+
// In this variant, the switch in behaviour happens at an intermediate protocol (FauxtingPoint)
13+
// rather than at concrete types (Fauxt).
14+
//
15+
// Unfortunately to make this work, we have to go even further into the weeds and make use of
16+
// @_nonoverride to provide a protocol-level entry to rank against Comparable.<, because the type
17+
// system happens to prefer protocol-level entries to extension-level entries when ranking
18+
// overrides.
19+
20+
// Count calls to the different comparison operators.
21+
public var comparedAsComparablesCount : Int = 0
22+
public var comparedAsFauxtingPointsCount : Int = 0
23+
24+
public protocol FauxtingPoint : Comparable {
25+
static var nan: Self { get }
26+
static var one: Self { get }
27+
static var two: Self { get }
28+
var bitPattern: UInt8 { get }
29+
@_nonoverride static func <(_ lhs: Self, _ rhs: Self) -> Bool
30+
}
31+
32+
public extension FauxtingPoint {
33+
// This version of < will be called in a context that only knows it has a Comparable.
34+
@_implements(Comparable, <(_:_:))
35+
static func _ComparableLessThan(_ lhs: Self, _ rhs: Self) -> Bool {
36+
print("compared as Comparables")
37+
comparedAsComparablesCount += 1
38+
return lhs.bitPattern < rhs.bitPattern
39+
}
40+
// This version of < will be called in a context that knows it has FauxtingPoint.
41+
static func <(_ lhs: Self, _ rhs: Self) -> Bool {
42+
print("compared as FauxtingPoint")
43+
comparedAsFauxtingPointsCount += 1
44+
if lhs == Self.nan || rhs == Self.nan {
45+
return false
46+
} else {
47+
return lhs.bitPattern < rhs.bitPattern
48+
}
49+
}
50+
}
51+
52+
public enum State {
53+
case Nan
54+
case One
55+
case Two
56+
}
57+
58+
public struct Fauxt {
59+
let state: State
60+
init(_ s: State) {
61+
state = s
62+
}
63+
public static var nan: Fauxt {
64+
return Fauxt(State.Nan)
65+
}
66+
public static var one: Fauxt {
67+
return Fauxt(State.One)
68+
}
69+
public static var two: Fauxt {
70+
return Fauxt(State.Two)
71+
}
72+
}
73+
74+
extension Fauxt: FauxtingPoint {
75+
// Requirement from FauxtingPoint
76+
public var bitPattern: UInt8 {
77+
switch state {
78+
case .One:
79+
return 1
80+
case .Two:
81+
return 2
82+
case .Nan:
83+
return 0xff
84+
}
85+
}
86+
}
87+
88+
public extension Fauxt {
89+
}
90+
91+
public func compare_Comparables<T:Comparable>(_ x: T, _ y: T) -> Bool {
92+
return x < y
93+
}
94+
95+
public func compare_FauxtingPoint<T:FauxtingPoint>(_ x: T, _ y: T) -> Bool {
96+
return x < y
97+
}
98+
99+
public func compare_Fauxts(_ x: Fauxt, _ y: Fauxt) -> Bool {
100+
return x < y
101+
}
102+
103+
public func main() {
104+
assert(compare_Comparables(Fauxt.one, Fauxt.two))
105+
assert(comparedAsComparablesCount == 1)
106+
// CHECK: compared as Comparables
107+
assert(compare_Comparables(Fauxt.one, Fauxt.nan))
108+
assert(comparedAsComparablesCount == 2)
109+
// CHECK: compared as Comparables
110+
assert(!compare_Comparables(Fauxt.nan, Fauxt.one))
111+
assert(comparedAsComparablesCount == 3)
112+
// CHECK: compared as Comparables
113+
114+
assert(compare_FauxtingPoint(Fauxt.one, Fauxt.two))
115+
assert(comparedAsFauxtingPointsCount == 1)
116+
// CHECK: compared as FauxtingPoint
117+
assert(!compare_FauxtingPoint(Fauxt.one, Fauxt.nan))
118+
assert(comparedAsFauxtingPointsCount == 2)
119+
// CHECK: compared as FauxtingPoint
120+
assert(!compare_FauxtingPoint(Fauxt.nan, Fauxt.one))
121+
assert(comparedAsFauxtingPointsCount == 3)
122+
// CHECK: compared as FauxtingPoint
123+
124+
assert(compare_Fauxts(Fauxt.one, Fauxt.two))
125+
assert(comparedAsFauxtingPointsCount == 4)
126+
// CHECK: compared as FauxtingPoint
127+
assert(!compare_Fauxts(Fauxt.one, Fauxt.nan))
128+
assert(comparedAsFauxtingPointsCount == 5)
129+
// CHECK: compared as FauxtingPoint
130+
assert(!compare_Fauxts(Fauxt.nan, Fauxt.one))
131+
assert(comparedAsFauxtingPointsCount == 6)
132+
// CHECK: compared as FauxtingPoint
133+
}

0 commit comments

Comments
 (0)