Skip to content

Commit 868afc6

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
1 parent a407b13 commit 868afc6

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -822,17 +822,27 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
822822
continue;
823823
}
824824

825-
// Dynamic member lookup through a keypath is better than one using string
826-
// because it carries more type information.
827-
if (choice1.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup &&
828-
choice2.getKind() == OverloadChoiceKind::DynamicMemberLookup) {
829-
score1 += weight;
825+
if (choice1.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
826+
if (choice2.getKind() == OverloadChoiceKind::DynamicMemberLookup)
827+
// Dynamic member lookup through a keypath is better than one using
828+
// string because it carries more type information.
829+
score1 += weight;
830+
else
831+
// Otherwise let's prefer non-dynamic declaration.
832+
score2 += weight;
833+
830834
continue;
831835
}
832836

833-
if (choice1.getKind() == OverloadChoiceKind::DynamicMemberLookup &&
834-
choice2.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
835-
score2 += weight;
837+
if (choice2.getKind() == OverloadChoiceKind::KeyPathDynamicMemberLookup) {
838+
if (choice1.getKind() == OverloadChoiceKind::DynamicMemberLookup)
839+
// Dynamic member lookup through a keypath is better than one using
840+
// string because it carries more type information.
841+
score2 += weight;
842+
else
843+
// Otherwise let's prefer non-dynamic declaration.
844+
score1 += weight;
845+
836846
continue;
837847
}
838848

test/Constraints/keypath_dynamic_member_lookup.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,26 @@ func make_sure_delayed_keypath_dynamic_member_works() {
367367
}
368368
}
369369
}
370+
371+
372+
// SR-11465 - Ambiguity in expression which matches both dynamic member lookup and declaration from constrained extension
373+
374+
@dynamicMemberLookup
375+
struct SR_11465<RawValue> {
376+
var rawValue: RawValue
377+
378+
subscript<Subject>(dynamicMember keyPath: KeyPath<RawValue, Subject>) -> Subject {
379+
rawValue[keyPath: keyPath]
380+
}
381+
}
382+
383+
extension SR_11465: Hashable, Equatable where RawValue: Hashable {
384+
func hash(into hasher: inout Hasher) {
385+
hasher.combine(self.rawValue)
386+
}
387+
}
388+
389+
func test_constrained_ext_vs_dynamic_member() {
390+
// CHECK: function_ref @$s29keypath_dynamic_member_lookup8SR_11465VAASHRzlE9hashValueSivg
391+
_ = SR_11465<Int>(rawValue: 1).hashValue // Ok, keep choice from constrained extension
392+
}

0 commit comments

Comments
 (0)