Skip to content

Commit 41f6eb9

Browse files
committed
[ConstraintSystem] Don't introduce implicit keypath choice for keypath dynamic member lookup
1 parent 7032095 commit 41f6eb9

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3537,6 +3537,10 @@ static bool hasDynamicMemberLookupAttribute(Type type,
35373537
return result;
35383538
}
35393539

3540+
static bool isKeyPathDynamicMemberLookup(ConstraintLocator *locator) {
3541+
auto path = locator ? locator->getPath() : None;
3542+
return !path.empty() && path.back().isKeyPathDynamicMember();
3543+
}
35403544

35413545
/// Given a ValueMember, UnresolvedValueMember, or TypeMember constraint,
35423546
/// perform a lookup into the specified base type to find a candidate list.
@@ -3568,10 +3572,15 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
35683572
// Okay, start building up the result list.
35693573
MemberLookupResult result;
35703574
result.OverallResult = MemberLookupResult::HasResults;
3571-
3575+
35723576
// If we're looking for a subscript, consider key path operations.
3577+
//
3578+
// TODO: This logic needs to be refactored to make sure that implicit
3579+
// keypath result is only introduced when it makes sense e.g. if there
3580+
// is a single argument with `keypath:` label or `\.` syntax is used.
35733581
if (memberName.isSimpleName() &&
3574-
memberName.getBaseName().getKind() == DeclBaseName::Kind::Subscript) {
3582+
memberName.getBaseName().getKind() == DeclBaseName::Kind::Subscript &&
3583+
!isKeyPathDynamicMemberLookup(memberLocator)) {
35753584
result.ViableCandidates.push_back(
35763585
OverloadChoice(baseTy, OverloadChoiceKind::KeyPathApplication));
35773586
}
@@ -3831,20 +3840,18 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
38313840
// based dynamic member lookup. Since it's unknown upfront
38323841
// what kind of declaration lookup is going to find, let's
38333842
// double check here that given keypath is appropriate for it.
3834-
if (memberLocator) {
3843+
if (isKeyPathDynamicMemberLookup(memberLocator)) {
38353844
auto path = memberLocator->getPath();
3836-
if (!path.empty() && path.back().isKeyPathDynamicMember()) {
3837-
auto *keyPath = path.back().getKeyPath();
3838-
if (auto *storage = dyn_cast<AbstractStorageDecl>(decl)) {
3839-
// If this is an attempt to access read-only member via
3840-
// writable key path, let's fail this choice early.
3841-
if (isReadOnlyKeyPathComponent(storage) &&
3842-
keyPath == getASTContext().getWritableKeyPathDecl()) {
3843-
result.addUnviable(
3844-
candidate,
3845-
MemberLookupResult::UR_WritableKeyPathOnReadOnlyMember);
3846-
return;
3847-
}
3845+
auto *keyPath = path.back().getKeyPath();
3846+
if (auto *storage = dyn_cast<AbstractStorageDecl>(decl)) {
3847+
// If this is an attempt to access read-only member via
3848+
// writable key path, let's fail this choice early.
3849+
if (isReadOnlyKeyPathComponent(storage) &&
3850+
keyPath == getASTContext().getWritableKeyPathDecl()) {
3851+
result.addUnviable(
3852+
candidate,
3853+
MemberLookupResult::UR_WritableKeyPathOnReadOnlyMember);
3854+
return;
38483855
}
38493856
}
38503857
}

test/attr/attr_dynamic_member_lookup.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ struct WithTrailingClosure {
601601

602602
func keypath_with_trailing_closure_subscript(_ ty: inout SubscriptLens<WithTrailingClosure>) {
603603
_ = ty[0] { 42 } // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}}
604+
_ = ty[0] { 42 } = 0 // FIXME(diagnostics): Once keypath related diagnostics are using fixes, "ambiguous" error would disappear
605+
// expected-error@-1 {{subscript index of type '() -> Int' in a key path must be Hashable}}
606+
// expected-error@-2 {{type of expression is ambiguous without more context}}
604607
_ = ty[] { 42 } // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}}
605608
_ = ty[] { 42 } = 0 // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}}
606609
}

0 commit comments

Comments
 (0)