Skip to content

Commit 4db2cf7

Browse files
authored
Merge pull request swiftlang#70076 from xedin/sendable-keypath-literals
[ConstraintSystem] Implement sendability inference for key path expressions
2 parents cc858ab + 511dad5 commit 4db2cf7

20 files changed

+321
-55
lines changed

include/swift/AST/Expr.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6101,11 +6101,11 @@ class KeyPathExpr : public Expr {
61016101
ParsedPath = path;
61026102
}
61036103

6104-
TypeRepr *getRootType() const {
6104+
TypeRepr *getExplicitRootType() const {
61056105
assert(!isObjC() && "cannot get root type of ObjC keypath");
61066106
return RootType;
61076107
}
6108-
void setRootType(TypeRepr *rootType) {
6108+
void setExplicitRootType(TypeRepr *rootType) {
61096109
assert(!isObjC() && "cannot set root type of ObjC keypath");
61106110
RootType = rootType;
61116111
}
@@ -6116,6 +6116,11 @@ class KeyPathExpr : public Expr {
61166116
/// True if this key path expression has a leading dot.
61176117
bool expectsContextualRoot() const { return HasLeadingDot; }
61186118

6119+
BoundGenericType *getKeyPathType() const;
6120+
6121+
Type getRootType() const;
6122+
Type getValueType() const;
6123+
61196124
static bool classof(const Expr *E) {
61206125
return E->getKind() == ExprKind::KeyPath;
61216126
}

include/swift/SIL/SILInstruction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3908,6 +3908,8 @@ class KeyPathInst final
39083908
}
39093909

39103910
public:
3911+
BoundGenericType *getKeyPathType() const;
3912+
39113913
KeyPathPattern *getPattern() const;
39123914
bool hasPattern() const { return (bool)Pattern; }
39133915

include/swift/Sema/ConstraintSystem.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,14 @@ enum TypeVariableOptions {
339339
TVO_PackExpansion = 0x40,
340340
};
341341

342-
enum class KeyPathCapability : uint8_t {
342+
enum class KeyPathMutability : uint8_t {
343343
ReadOnly,
344344
Writable,
345345
ReferenceWritable
346346
};
347347

348+
using KeyPathCapability = std::pair<KeyPathMutability, /*isSendable=*/bool>;
349+
348350
/// The implementation object for a type variable used within the
349351
/// constraint-solving type checker.
350352
///
@@ -6311,7 +6313,7 @@ class TypeVarRefCollector : public ASTWalker {
63116313
};
63126314

63136315
/// Determine whether given type is a known one
6314-
/// for a key path `{Writable, ReferenceWritable}KeyPath`.
6316+
/// for a key path `{Any, Partial, Writable, ReferenceWritable}KeyPath`.
63156317
bool isKnownKeyPathType(Type type);
63166318

63176319
/// Determine whether given declaration is one for a key path

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
12801280
}
12811281

12821282
if (!E->isObjC()) {
1283-
auto rootType = E->getRootType();
1283+
auto rootType = E->getExplicitRootType();
12841284
if (rootType && doIt(rootType))
12851285
return nullptr;
12861286
}

lib/AST/Expr.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/ASTVisitor.h"
2222
#include "swift/AST/Decl.h" // FIXME: Bad dependency
23+
#include "swift/AST/ExistentialLayout.h"
2324
#include "swift/AST/MacroDiscriminatorContext.h"
2425
#include "swift/AST/ParameterList.h"
2526
#include "swift/AST/Stmt.h"
@@ -2443,6 +2444,35 @@ llvm::Optional<unsigned> KeyPathExpr::findComponentWithSubscriptArg(Expr *arg) {
24432444
return llvm::None;
24442445
}
24452446

2447+
BoundGenericType *KeyPathExpr::getKeyPathType() const {
2448+
auto type = getType();
2449+
if (!type)
2450+
return nullptr;
2451+
2452+
if (auto *existentialTy = type->getAs<ExistentialType>()) {
2453+
auto *sendableTy =
2454+
existentialTy->getConstraintType()->castTo<ProtocolCompositionType>();
2455+
assert(sendableTy->getMembers().size() == 2);
2456+
type = sendableTy->getExistentialLayout().explicitSuperclass;
2457+
assert(type->isKeyPath() || type->isWritableKeyPath() ||
2458+
type->isReferenceWritableKeyPath());
2459+
}
2460+
2461+
return type->castTo<BoundGenericType>();
2462+
}
2463+
2464+
Type KeyPathExpr::getRootType() const {
2465+
auto keyPathTy = getKeyPathType();
2466+
assert(keyPathTy && "key path type has not been set yet");
2467+
return keyPathTy->getGenericArgs()[0];
2468+
}
2469+
2470+
Type KeyPathExpr::getValueType() const {
2471+
auto keyPathTy = getKeyPathType();
2472+
assert(keyPathTy && "key path type has not been set yet");
2473+
return keyPathTy->getGenericArgs()[1];
2474+
}
2475+
24462476
KeyPathExpr::Component KeyPathExpr::Component::forSubscript(
24472477
ASTContext &ctx, ConcreteDeclRef subscript, ArgumentList *argList,
24482478
Type elementType, ArrayRef<ProtocolConformanceRef> indexHashables) {

lib/IDE/KeyPathCompletion.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ void KeyPathTypeCheckCompletionCallback::sawSolutionImpl(
3737
if (ComponentIndex == 0) {
3838
// We are completing on the root and need to extract the key path's root
3939
// type.
40-
if (KeyPath->getRootType()) {
41-
BaseType = S.getResolvedType(KeyPath->getRootType());
40+
if (auto *rootTy = KeyPath->getExplicitRootType()) {
41+
BaseType = S.getResolvedType(rootTy);
4242
} else {
4343
// The key path doesn't have a root TypeRepr set, so we can't look the key
4444
// path's root up through it. Build a constraint locator and look the

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7123,7 +7123,8 @@ void IRGenSILFunction::visitKeyPathInst(swift::KeyPathInst *I) {
71237123
emitDeallocateDynamicAlloca(*dynamicArgsBuf);
71247124
}
71257125

7126-
auto resultStorageTy = IGM.getTypeInfo(I->getType()).getStorageType();
7126+
auto loweredKeyPathTy = IGM.getLoweredType(I->getKeyPathType());
7127+
auto resultStorageTy = IGM.getTypeInfo(loweredKeyPathTy).getStorageType();
71277128

71287129
Explosion e;
71297130
e.add(Builder.CreateBitCast(call, resultStorageTy));

lib/SIL/IR/SILInstructions.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//
1515
//===----------------------------------------------------------------------===//
1616

17+
#include "swift/AST/ExistentialLayout.h"
1718
#include "swift/AST/Expr.h"
1819
#include "swift/AST/ProtocolConformance.h"
1920
#include "swift/Basic/AssertImplements.h"
@@ -2966,6 +2967,17 @@ KeyPathInst::~KeyPathInst() {
29662967
operand.~Operand();
29672968
}
29682969

2970+
BoundGenericType *KeyPathInst::getKeyPathType() const {
2971+
auto kpTy = getType();
2972+
2973+
if (auto existential = kpTy.getAs<ExistentialType>()) {
2974+
return existential->getExistentialLayout()
2975+
.explicitSuperclass->castTo<BoundGenericType>();
2976+
}
2977+
2978+
return kpTy.getAs<BoundGenericType>();
2979+
}
2980+
29692981
KeyPathPattern *KeyPathInst::getPattern() const {
29702982
assert(Pattern && "pattern was reset!");
29712983
return Pattern;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5423,8 +5423,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
54235423
auto kpTy = KPI->getType();
54245424

54255425
require(kpTy.isObject(), "keypath result must be an object type");
5426-
5427-
auto kpBGT = kpTy.getAs<BoundGenericType>();
5426+
5427+
auto *kpBGT = KPI->getKeyPathType();
5428+
54285429
require(kpBGT, "keypath result must be a generic type");
54295430
require(kpBGT->isKeyPath() ||
54305431
kpBGT->isWritableKeyPath() ||

lib/SILGen/SILGenExpr.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4140,9 +4140,8 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
41404140
SmallVector<KeyPathPatternComponent, 4> loweredComponents;
41414141
auto loweredTy = SGF.getLoweredType(E->getType());
41424142

4143-
CanType rootTy = E->getType()->castTo<BoundGenericType>()->getGenericArgs()[0]
4144-
->getCanonicalType();
4145-
4143+
CanType rootTy = E->getRootType()->getCanonicalType();
4144+
41464145
bool needsGenericContext = false;
41474146
if (rootTy->hasArchetype()) {
41484147
needsGenericContext = true;

0 commit comments

Comments
 (0)