@@ -398,46 +398,36 @@ - (BOOL)isEqual:(id)other {
398
398
399
399
// Get Swift type for self and other
400
400
auto selfMetadata = _swift_getClassOfAllocated (self);
401
- auto otherMetadata = _swift_getClassOfAllocated (other);
402
401
403
- // Find common parent class
404
- const ClassMetadata * parentMetadata = NULL ;
405
- if (selfMetadata == otherMetadata) {
406
- parentMetadata = selfMetadata;
407
- } else {
408
- // Collect parents of self
409
- std::unordered_set<const ClassMetadata *> selfAncestors;
410
- for (auto m = selfMetadata; m != NULL ; m = m->Superclass ) {
411
- selfAncestors.emplace (m);
412
- }
413
- // Find first parent of other that is also a parent of self
414
- for (auto m = otherMetadata; m != NULL ; m = m->Superclass ) {
415
- if (selfAncestors.find (m) != selfAncestors.end ()) {
416
- parentMetadata = m;
417
- break ;
418
- }
419
- }
420
- // If there's no common parent class, we can't compare them
421
- if (parentMetadata == NULL ) {
422
- return NO ;
423
- }
424
- }
425
- // Note: Because `self` subclasses SwiftObject, we know parentMetadata
426
- // must be a Swift type or SwiftObject itself.
427
-
428
- // This will work for types that implement Hashable or only Equatable.
429
- // In the latter case, there is a risk that `-hash` and `-isEqual:` might
430
- // be incompatible. See notes above for `-hash`
402
+ // We use Equatable conformance, which will also work for types that implement
403
+ // Hashable. If the type implements Equatable but not Hashable, there is a
404
+ // risk that `-hash` and `-isEqual:` might be incompatible. See notes above
405
+ // for `-hash`
431
406
auto equatableConformance =
432
- reinterpret_cast <const equatable_support::EquatableWitnessTable *>(
433
- swift_conformsToProtocolCommon (
434
- parentMetadata, &equatable_support::EquatableProtocolDescriptor));
407
+ swift_conformsToProtocolCommon (
408
+ selfMetadata, &equatable_support::EquatableProtocolDescriptor);
435
409
if (equatableConformance == NULL ) {
436
410
return NO ;
437
411
}
438
412
439
- return _swift_stdlib_Equatable_isEqual_indirect (
440
- &self, &other, parentMetadata, equatableConformance);
413
+ // Is the other object a subclass of the parent that
414
+ // actually defined this conformance?
415
+ auto conformingParent =
416
+ findConformingSuperclass (selfMetadata, equatableConformance->getDescription ());
417
+ auto otherMetadata = _swift_getClassOfAllocated (other);
418
+ if (_swift_class_isSubclass (otherMetadata, conformingParent)) {
419
+ // We now have an equatable conformance of a common parent
420
+ // of both object types:
421
+ return _swift_stdlib_Equatable_isEqual_indirect (
422
+ &self,
423
+ &other,
424
+ conformingParent,
425
+ reinterpret_cast <const equatable_support::EquatableWitnessTable *>(
426
+ equatableConformance)
427
+ );
428
+ }
429
+
430
+ return NO ;
441
431
}
442
432
443
433
- (id )performSelector : (SEL )aSelector {
0 commit comments