mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Completion] Fix Sendable KeyPath dynamic member subscripts
Introduce `getKeyPathTypeForDynamicMemberLookup` which returns the KeyPath type, and can be used from both `RootAndResultTypeOfKeypathDynamicMemberRequest` and `isValidKeyPathDynamicMemberLookup`. This ensures we look to the superclass for e.g protocol compositions with `Sendable`. This also means we now return an interface type, which is what the client of `RootAndResultTypeOfKeypathDynamicMemberRequest` wanted anyway. rdar://138418296
This commit is contained in:
@@ -643,8 +643,7 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD,
|
||||
|
||||
// If the keyPath result type has type parameters, that might affect the
|
||||
// subscript result type.
|
||||
auto keyPathResultTy =
|
||||
getResultTypeOfKeypathDynamicMember(SD)->mapTypeOutOfContext();
|
||||
auto keyPathResultTy = getResultTypeOfKeypathDynamicMember(SD);
|
||||
if (keyPathResultTy->hasTypeParameter()) {
|
||||
auto keyPathRootTy = getRootTypeOfKeypathDynamicMember(SD).subst(
|
||||
QueryTypeSubstitutionMap{subs},
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
#include "swift/AST/ConformanceLookup.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ExistentialLayout.h"
|
||||
#include "swift/AST/NameLookup.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/Basic/SourceManager.h"
|
||||
@@ -257,15 +258,11 @@ TypeRelationCheckRequest::evaluate(Evaluator &evaluator,
|
||||
TypePair
|
||||
RootAndResultTypeOfKeypathDynamicMemberRequest::evaluate(Evaluator &evaluator,
|
||||
SubscriptDecl *subscript) const {
|
||||
if (!isValidKeyPathDynamicMemberLookup(subscript))
|
||||
return TypePair();
|
||||
|
||||
const auto *param = subscript->getIndices()->get(0);
|
||||
auto keyPathType = param->getTypeInContext()->getAs<BoundGenericType>();
|
||||
auto keyPathType = getKeyPathTypeForDynamicMemberLookup(subscript);
|
||||
if (!keyPathType)
|
||||
return TypePair();
|
||||
|
||||
auto genericArgs = keyPathType->getGenericArgs();
|
||||
assert(!genericArgs.empty() && genericArgs.size() == 2 &&
|
||||
"invalid keypath dynamic member");
|
||||
assert(genericArgs.size() == 2 && "invalid keypath dynamic member");
|
||||
return TypePair(genericArgs[0], genericArgs[1]);
|
||||
}
|
||||
|
||||
@@ -1969,12 +1969,13 @@ bool swift::isValidStringDynamicMemberLookup(SubscriptDecl *decl,
|
||||
paramType, KnownProtocolKind::ExpressibleByStringLiteral);
|
||||
}
|
||||
|
||||
bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl,
|
||||
bool ignoreLabel) {
|
||||
BoundGenericType *
|
||||
swift::getKeyPathTypeForDynamicMemberLookup(SubscriptDecl *decl,
|
||||
bool ignoreLabel) {
|
||||
auto &ctx = decl->getASTContext();
|
||||
if (!hasSingleNonVariadicParam(decl, ctx.Id_dynamicMember,
|
||||
ignoreLabel))
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
auto paramTy = decl->getIndices()->get(0)->getInterfaceType();
|
||||
|
||||
@@ -1994,17 +1995,25 @@ bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl,
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
paramTy = layout.getSuperclass();
|
||||
if (!paramTy)
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return paramTy->isKeyPath() ||
|
||||
paramTy->isWritableKeyPath() ||
|
||||
paramTy->isReferenceWritableKeyPath();
|
||||
if (!paramTy->isKeyPath() &&
|
||||
!paramTy->isWritableKeyPath() &&
|
||||
!paramTy->isReferenceWritableKeyPath()) {
|
||||
return nullptr;
|
||||
}
|
||||
return paramTy->getAs<BoundGenericType>();
|
||||
}
|
||||
|
||||
bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl,
|
||||
bool ignoreLabel) {
|
||||
return bool(getKeyPathTypeForDynamicMemberLookup(decl, ignoreLabel));
|
||||
}
|
||||
|
||||
/// The @dynamicMemberLookup attribute is only allowed on types that have at
|
||||
|
||||
@@ -1271,6 +1271,18 @@ bool isValidDynamicMemberLookupSubscript(SubscriptDecl *decl,
|
||||
bool isValidStringDynamicMemberLookup(SubscriptDecl *decl,
|
||||
bool ignoreLabel = false);
|
||||
|
||||
/// Returns the KeyPath parameter type for a valid implementation of
|
||||
/// the `subscript(dynamicMember: {Writable}KeyPath<...>)` requirement for
|
||||
/// @dynamicMemberLookup.
|
||||
/// The method is given to be defined as `subscript(dynamicMember:)` which
|
||||
/// takes a single non-variadic parameter of `{Writable}KeyPath<T, U>` type.
|
||||
///
|
||||
/// Returns null if the given subscript is not a valid dynamic member lookup
|
||||
/// implementation.
|
||||
BoundGenericType *
|
||||
getKeyPathTypeForDynamicMemberLookup(SubscriptDecl *decl,
|
||||
bool ignoreLabel = false);
|
||||
|
||||
/// Returns true if the given subscript method is an valid implementation of
|
||||
/// the `subscript(dynamicMember: {Writable}KeyPath<...>)` requirement for
|
||||
/// @dynamicMemberLookup.
|
||||
|
||||
@@ -356,3 +356,17 @@ func testSubscriptOnProtocolExtension(dyn: DynamicLookupConcrete) {
|
||||
// testSubscriptOnProtocolExt: Decl[InstanceVar]/CurrNominal: x[#Int#];
|
||||
// testSubscriptOnProtocolExt: Decl[InstanceVar]/CurrNominal: y[#Int#];
|
||||
}
|
||||
|
||||
// https://github.com/swiftlang/swift/issues/77035
|
||||
@dynamicMemberLookup
|
||||
struct HasSendableKeyPath<T> {
|
||||
subscript<U>(dynamicMember keyPath: KeyPath<T, U> & Sendable) -> HasSendableKeyPath<U> {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
func testSendableKeyPath(_ x: HasSendableKeyPath<Point>) {
|
||||
x.#^SENDABLE_KEYPATH_POINT^#
|
||||
// SENDABLE_KEYPATH_POINT-DAG: Decl[InstanceVar]/CurrNominal: x[#HasSendableKeyPath<Int>#]; name=x
|
||||
// SENDABLE_KEYPATH_POINT-DAG: Decl[InstanceVar]/CurrNominal: y[#HasSendableKeyPath<Int>#]; name=y
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user