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();
4141// / Whether to use legacy semantics when unboxing __SwiftValue
4242bool useLegacySwiftValueUnboxingInCasting ();
4343
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+
4450} // namespace bincompat
4551
4652} // namespace runtime
Original file line number Diff line number Diff line change @@ -228,6 +228,30 @@ bool useLegacySwiftValueUnboxingInCasting() {
228228#endif
229229}
230230
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+
231255} // namespace bincompat
232256
233257} // namespace runtime
Original file line number Diff line number Diff line change @@ -376,6 +376,11 @@ + (BOOL)conformsToProtocol:(Protocol*)proto {
376376}
377377
378378- (NSUInteger )hash {
379+ if (runtime::bincompat::useLegacySwiftObjCHashing ()) {
380+ // Legacy behavior: Don't proxy to Swift Hashable
381+ return (NSUInteger )self;
382+ }
383+
379384 auto selfMetadata = _swift_getClassOfAllocated (self);
380385
381386 // If it's Hashable, use that
@@ -423,6 +428,11 @@ - (BOOL)isEqual:(id)other {
423428 if (self == other) {
424429 return YES ;
425430 }
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+
426436
427437 // Get Swift type for self and other
428438 auto selfMetadata = _swift_getClassOfAllocated (self);
Original file line number Diff line number Diff line change 2424#include " SwiftObject.h"
2525#include " SwiftValue.h"
2626#include " swift/Basic/Lazy.h"
27+ #include " swift/Runtime/Bincompat.h"
2728#include " swift/Runtime/Casting.h"
2829#include " swift/Runtime/HeapObject.h"
2930#include " swift/Runtime/Metadata.h"
@@ -429,6 +430,11 @@ - (BOOL)isEqual:(id)other {
429430 }
430431 }
431432
433+ if (runtime::bincompat::useLegacySwiftObjCHashing ()) {
434+ // Legacy behavior only proxies isEqual: for Hashable, not Equatable
435+ return NO ;
436+ }
437+
432438 if (auto equatableConformance = selfHeader->getEquatableConformance ()) {
433439 if (auto selfEquatableBaseType = selfHeader->getEquatableBaseType ()) {
434440 auto otherEquatableBaseType = otherHeader->getEquatableBaseType ();
@@ -458,6 +464,11 @@ - (NSUInteger)hash {
458464 selfHeader->type , hashableConformance);
459465 }
460466
467+ if (!runtime::bincompat::useLegacySwiftObjCHashing ()) {
468+ // Legacy behavior doesn't honor Equatable conformance, only Hashable
469+ return (NSUInteger )self;
470+ }
471+
461472 // If Swift type is Equatable but not Hashable,
462473 // we have to return something here that is compatible
463474 // with the `isEqual:` above.
You can’t perform that action at this time.
0 commit comments