File tree Expand file tree Collapse file tree 4 files changed +51
-0
lines changed Expand file tree Collapse file tree 4 files changed +51
-0
lines changed Original file line number Diff line number Diff line change @@ -41,6 +41,12 @@ bool useLegacyObjCBoxingInCasting();
41
41
// / Whether to use legacy semantics when unboxing __SwiftValue
42
42
bool useLegacySwiftValueUnboxingInCasting ();
43
43
44
+ // / Legacy semantics use trivial implementations for -hashValue/-isEqual:
45
+ // / requests from ObjC to Swift values.
46
+ // / New semantics attempt to dispatch to Swift Hashable/Equatable conformances
47
+ // / if present.
48
+ bool useLegacySwiftObjCHashing ();
49
+
44
50
} // namespace bincompat
45
51
46
52
} // namespace runtime
Original file line number Diff line number Diff line change @@ -228,6 +228,30 @@ bool useLegacySwiftValueUnboxingInCasting() {
228
228
#endif
229
229
}
230
230
231
+ // Controls how ObjC -hashValue and -isEqual are handled
232
+ // by Swift objects.
233
+ // There are two basic semantics:
234
+ // * pointer: -hashValue returns pointer, -isEqual: tests pointer equality
235
+ // * proxy: -hashValue calls on Hashable conformance, -isEqual: calls Equatable conformance
236
+ //
237
+ // Legacy handling:
238
+ // * Swift struct/enum values that implement Hashable: proxy -hashValue and -isEqual:
239
+ // * Swift struct/enum values that implement Equatable but not Hashable: pointer semantics
240
+ // * Swift class values regardless of hashable/Equatable support: pointer semantics
241
+ //
242
+ // New behavior:
243
+ // * Swift struct/enum/class values that implement Hashable: proxy -hashValue and -isEqual:
244
+ // * Swift struct/enum/class values that implement Equatable but not Hashable: proxy -isEqual:, constant -hashValue
245
+ // * All other cases: pointer semantics
246
+ //
247
+ bool useLegacySwiftObjCHashing () {
248
+ #if BINARY_COMPATIBILITY_APPLE
249
+ return true ; // For now, legacy behavior on Apple OSes
250
+ #else
251
+ return false ; // Always use the new behavior on non-Apple OSes
252
+ #endif
253
+ }
254
+
231
255
} // namespace bincompat
232
256
233
257
} // namespace runtime
Original file line number Diff line number Diff line change @@ -376,6 +376,11 @@ + (BOOL)conformsToProtocol:(Protocol*)proto {
376
376
}
377
377
378
378
- (NSUInteger )hash {
379
+ if (runtime::bincompat::useLegacySwiftObjCHashing ()) {
380
+ // Legacy behavior: Don't proxy to Swift Hashable
381
+ return (NSUInteger )self;
382
+ }
383
+
379
384
auto selfMetadata = _swift_getClassOfAllocated (self);
380
385
381
386
// If it's Hashable, use that
@@ -423,6 +428,11 @@ - (BOOL)isEqual:(id)other {
423
428
if (self == other) {
424
429
return YES ;
425
430
}
431
+ if (runtime::bincompat::useLegacySwiftObjCHashing ()) {
432
+ // Legacy behavior: Don't proxy to Swift Hashable or Equatable
433
+ return NO ; // We know the ids are different
434
+ }
435
+
426
436
427
437
// Get Swift type for self and other
428
438
auto selfMetadata = _swift_getClassOfAllocated (self);
Original file line number Diff line number Diff line change 24
24
#include " SwiftObject.h"
25
25
#include " SwiftValue.h"
26
26
#include " swift/Basic/Lazy.h"
27
+ #include " swift/Runtime/Bincompat.h"
27
28
#include " swift/Runtime/Casting.h"
28
29
#include " swift/Runtime/HeapObject.h"
29
30
#include " swift/Runtime/Metadata.h"
@@ -429,6 +430,11 @@ - (BOOL)isEqual:(id)other {
429
430
}
430
431
}
431
432
433
+ if (runtime::bincompat::useLegacySwiftObjCHashing ()) {
434
+ // Legacy behavior only proxies isEqual: for Hashable, not Equatable
435
+ return NO ;
436
+ }
437
+
432
438
if (auto equatableConformance = selfHeader->getEquatableConformance ()) {
433
439
if (auto selfEquatableBaseType = selfHeader->getEquatableBaseType ()) {
434
440
auto otherEquatableBaseType = otherHeader->getEquatableBaseType ();
@@ -458,6 +464,11 @@ - (NSUInteger)hash {
458
464
selfHeader->type , hashableConformance);
459
465
}
460
466
467
+ if (!runtime::bincompat::useLegacySwiftObjCHashing ()) {
468
+ // Legacy behavior doesn't honor Equatable conformance, only Hashable
469
+ return (NSUInteger )self;
470
+ }
471
+
461
472
// If Swift type is Equatable but not Hashable,
462
473
// we have to return something here that is compatible
463
474
// with the `isEqual:` above.
You can’t perform that action at this time.
0 commit comments