Sema: Handle ArchetypeType and DynamicSelfType in determineBestChoicesInContext()

This fixes a regression introduced in https://github.com/swiftlang/swift/pull/82574.

The test case demonstrates the issue: we would incorrectly choose the base class
overload of == if one of the parameters was an archetype or dynamic Self.

Fixes rdar://156454697.
This commit is contained in:
Slava Pestov
2025-07-23 17:09:30 -04:00
parent 858383c71d
commit 30c7f4afa7
2 changed files with 84 additions and 0 deletions

View File

@@ -1159,6 +1159,16 @@ static void determineBestChoicesInContext(
});
}
if (auto *selfType = candidateType->getAs<DynamicSelfType>()) {
candidateType = selfType->getSelfType();
}
if (auto *archetypeType = candidateType->getAs<ArchetypeType>()) {
candidateType = archetypeType->getSuperclass();
if (!candidateType)
return false;
}
auto *subclassDecl = candidateType->getClassOrBoundGenericClass();
auto *superclassDecl = superclassType->getClassOrBoundGenericClass();

View File

@@ -0,0 +1,74 @@
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
// rdar://156454697
// The appearance of DynamicSelfType as an argument type to ==
// would lead us to choose the Base.== overload, which is less
// "specific" than Derived.==. There was a similar bug with
// archetypes.
//
// This is a SILGen test, to check the overload choice.
public class Base: Equatable {
public static func ==(lhs: Base, rhs: Base) -> Bool {
return false
}
}
public class Derived: Base {
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2f1SbyF : $@convention(method) (@guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func f1() -> Bool {
return self == self
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2f2SbyF : $@convention(method) (@guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func f2() -> Bool {
let c = self as! Self
return self == c
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2f3SbyF : $@convention(method) (@guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func f3() -> Bool {
let c = self as! Self
return c == self
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2f4SbyF : $@convention(method) (@guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func f4() -> Bool {
let c = self as! Self
return c == c
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2g1ySbxACRbzlF : $@convention(method) <T where T : Derived> (@guaranteed T, @guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func g1<T: Derived>(_ c: T) -> Bool {
return self == c
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2g2ySbxACRbzlF : $@convention(method) <T where T : Derived> (@guaranteed T, @guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func g2<T: Derived>(_ c: T) -> Bool {
return c == self
}
// CHECK-LABEL: sil [ossa] @$s32subclass_shadows_operator_equals7DerivedC2g3ySbxACRbzlF : $@convention(method) <T where T : Derived> (@guaranteed T, @guaranteed Derived) -> Bool {
// CHECK: function_ref @$s32subclass_shadows_operator_equals7DerivedC2eeoiySbAC_ACtFZ : $@convention(method) (@guaranteed Derived, @guaranteed Derived, @thick Derived.Type) -> Bool
// CHECK: return
public func g3<T: Derived>(_ c: T) -> Bool {
return c == c
}
public static func ==(lhs: Derived, rhs: Derived) -> Bool {
return false
}
}