Skip to content

Commit 6eec2a6

Browse files
committed
[CSRanking] Always rank key path dynamic member choices lower than non-dynamic ones
This only comes into play when all other choices are coming from constrained extensions, because there is no way to determine upfront whether any are going to match it's better to be safe and add key path dynamic member choice to the set too. Resolves: [SR-11465](https://bugs.swift.org/browse/SR-11465) Resolves: rdar://problem/55314724 (cherry picked from commit 868afc6) (cherry picked from commit 23e7022)
1 parent 3203e2a commit 6eec2a6

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -880,17 +880,27 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
880880
continue;
881881
}
882882

883-
// Dynamic member lookup through a keypath is better than one using string
884-
// because it carries more type information.
885-
if (choice1.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup &&
886-
choice2.getKind() == OverloadChoiceKind::DynamicMemberLookup) {
887-
score1 += weight;
883+
if (choice1.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
884+
if (choice2.getKind() == OverloadChoiceKind::DynamicMemberLookup)
885+
// Dynamic member lookup through a keypath is better than one using
886+
// string because it carries more type information.
887+
score1 += weight;
888+
else
889+
// Otherwise let's prefer non-dynamic declaration.
890+
score2 += weight;
891+
888892
continue;
889893
}
890894

891-
if (choice1.getKind() == OverloadChoiceKind::DynamicMemberLookup &&
892-
choice2.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
893-
score2 += weight;
895+
if (choice2.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
896+
if (choice1.getKind() == OverloadChoiceKind::DynamicMemberLookup)
897+
// Dynamic member lookup through a keypath is better than one using
898+
// string because it carries more type information.
899+
score2 += weight;
900+
else
901+
// Otherwise let's prefer non-dynamic declaration.
902+
score1 += weight;
903+
894904
continue;
895905
}
896906

test/Constraints/keypath_dynamic_member_lookup.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,25 @@ func rdar52779809(_ ref1: Ref<S>, _ ref2: Ref<Q>) {
328328
// CHECK: function_ref @$s29keypath_dynamic_member_lookup3RefV0B6Memberqd__s7KeyPathCyxqd__G_tcluig
329329
_ = ref2.bar // Ok
330330
}
331+
332+
// SR-11465 - Ambiguity in expression which matches both dynamic member lookup and declaration from constrained extension
333+
334+
@dynamicMemberLookup
335+
struct SR_11465<RawValue> {
336+
var rawValue: RawValue
337+
338+
subscript<Subject>(dynamicMember keyPath: KeyPath<RawValue, Subject>) -> Subject {
339+
rawValue[keyPath: keyPath]
340+
}
341+
}
342+
343+
extension SR_11465: Hashable, Equatable where RawValue: Hashable {
344+
func hash(into hasher: inout Hasher) {
345+
hasher.combine(self.rawValue)
346+
}
347+
}
348+
349+
func test_constrained_ext_vs_dynamic_member() {
350+
// CHECK: function_ref @$s29keypath_dynamic_member_lookup8SR_11465VAASHRzlE9hashValueSivg
351+
_ = SR_11465<Int>(rawValue: 1).hashValue // Ok, keep choice from constrained extension
352+
}

0 commit comments

Comments
 (0)