Skip to content

Commit fac8822

Browse files
committed
Fix hash/isEqual interop conditionals, update tests
Github PR swiftlang#71620 mixed up one of the bincompat conditionals. It also had some errors in the tests for ObjC interop. For now, this leaves the legacy behavior in place for all Apple platforms.
1 parent 20021cf commit fac8822

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

stdlib/public/runtime/SwiftValue.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ - (NSUInteger)hash {
464464
selfHeader->type, hashableConformance);
465465
}
466466

467-
if (!runtime::bincompat::useLegacySwiftObjCHashing()) {
467+
if (runtime::bincompat::useLegacySwiftObjCHashing()) {
468468
// Legacy behavior doesn't honor Equatable conformance, only Hashable
469469
return (NSUInteger)self;
470470
}

test/stdlib/BridgeEquatableToObjC.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ BridgeEquatableToObjC.test("Bridge equatable struct") {
3232
let objcResult = objcA.isEqual(objcB)
3333

3434
expectEqual(swiftResult, true)
35+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
36+
// Apple platforms use old semantics for now...
37+
expectEqual(objcResult, false)
38+
#else
3539
expectEqual(objcResult, true)
40+
#endif
3641
}
3742

3843
BridgeEquatableToObjC.test("Bridge non-equatable struct") {

test/stdlib/SwiftObjectNSObject.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,12 @@ func TestSwiftObjectNSObjectAssertNoErrors()
9191
// Verify that Obj-C isEqual: provides same answer as Swift ==
9292
func TestEquatableEquals<T: Equatable & AnyObject>(_ e1: T, _ e2: T) {
9393
if e1 == e2 {
94+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
95+
// Legacy behavior: Equatable Swift does not imply == in ObjC
96+
TestSwiftObjectNSObjectNotEquals(e1, e2)
97+
#else
9498
TestSwiftObjectNSObjectEquals(e1, e2)
99+
#endif
95100
} else {
96101
TestSwiftObjectNSObjectNotEquals(e1, e2)
97102
}
@@ -104,14 +109,27 @@ func TestNonEquatableEquals(_ e1: AnyObject, _ e2: AnyObject) {
104109
// Verify that Obj-C hashValue matches Swift hashValue for Hashable types
105110
func TestHashable(_ h: H)
106111
{
112+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
113+
// Legacy behavior: Hash value is identity in ObjC
114+
TestSwiftObjectNSObjectDefaultHashValue(h)
115+
#else
116+
// New behavior: Hashable in Swift, same hash value in ObjC
107117
TestSwiftObjectNSObjectHashValue(h, h.hashValue)
118+
#endif
108119
}
109120
110121
// Test Obj-C hashValue for Swift types that are Equatable but not Hashable
111122
func TestEquatableHash(_ e: AnyObject)
112123
{
113-
// These should have a constant hash value
124+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
125+
// Legacy behavior: Equatable in Swift => ObjC hashes with identity
126+
TestSwiftObjectNSObjectDefaultHashValue(e)
127+
let msg = "Obj-C `-hash` ... type `SwiftObjectNSObject.\(type(of: e))` ... Equatable but not Hashable\n"
128+
fputs(msg, stderr)
129+
#else
130+
// New behavior: These should have a constant hash value
114131
TestSwiftObjectNSObjectHashValue(e, 1)
132+
#endif
115133
}
116134
117135
func TestNonEquatableHash(_ e: AnyObject)

test/stdlib/SwiftValueNSObject.swift

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,25 @@ func TestSwiftValueNSObjectDefaultHashValue(_: AnyObject)
7777
func TestSwiftValueNSObjectAssertNoErrors()
7878

7979
// Verify that Obj-C isEqual: provides same answer as Swift ==
80+
// This has been true for a long time for Hashable value types
81+
func TestHashableEquals<T: Equatable>(_ e1: T, _ e2: T) {
82+
if e1 == e2 {
83+
TestSwiftValueNSObjectEquals(e1 as AnyObject, e2 as AnyObject)
84+
} else {
85+
TestSwiftValueNSObjectNotEquals(e1 as AnyObject, e2 as AnyObject)
86+
}
87+
}
88+
89+
// Verify that Obj-C isEqual: provides same answer as Swift ==
90+
// This has not always been true for Equatable value types
8091
func TestEquatableEquals<T: Equatable>(_ e1: T, _ e2: T) {
8192
if e1 == e2 {
93+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
94+
// Legacy: Swift Equatable is not used in ObjC
95+
TestSwiftValueNSObjectNotEquals(e1 as AnyObject, e2 as AnyObject)
96+
#else
8297
TestSwiftValueNSObjectEquals(e1 as AnyObject, e2 as AnyObject)
98+
#endif
8399
} else {
84100
TestSwiftValueNSObjectNotEquals(e1 as AnyObject, e2 as AnyObject)
85101
}
@@ -143,9 +159,9 @@ if #available(OSX 10.12, iOS 10.0, *) {
143159
TestNonEquatableHash(D())
144160

145161
// Hashable types are also Equatable
146-
TestEquatableEquals(H(i:1), H(i:1))
147-
TestEquatableEquals(H(i:1), H(i:2))
148-
TestEquatableEquals(H(i:2), H(i:1))
162+
TestHashableEquals(H(i:1), H(i:1))
163+
TestHashableEquals(H(i:1), H(i:2))
164+
TestHashableEquals(H(i:2), H(i:1))
149165

150166
// Verify Obj-C hash value agrees with Swift
151167
TestHashable(H(i:1))

0 commit comments

Comments
 (0)