Skip to content

Commit e741147

Browse files
authored
Merge pull request #20459 from rjmccall/key-path-lvalue-emission
Always use the l-value logic for emitting key path applications
2 parents 4270bdd + c0285a7 commit e741147

File tree

7 files changed

+242
-184
lines changed

7 files changed

+242
-184
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3022,6 +3022,14 @@ static inline bool isRawPointerKind(PointerTypeKind PTK) {
30223022
llvm_unreachable("Unhandled PointerTypeKind in switch.");
30233023
}
30243024

3025+
enum KeyPathTypeKind : unsigned char {
3026+
KPTK_AnyKeyPath,
3027+
KPTK_PartialKeyPath,
3028+
KPTK_KeyPath,
3029+
KPTK_WritableKeyPath,
3030+
KPTK_ReferenceWritableKeyPath
3031+
};
3032+
30253033
/// NominalTypeDecl - a declaration of a nominal type, like a struct.
30263034
class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
30273035
SourceRange Braces;
@@ -3243,6 +3251,9 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
32433251
/// Is this the decl for Optional<T>?
32443252
bool isOptionalDecl() const;
32453253

3254+
/// Is this a key path type?
3255+
Optional<KeyPathTypeKind> getKeyPathTypeKind() const;
3256+
32463257
private:
32473258
/// Predicate used to filter StoredPropertyRange.
32483259
struct ToStoredProperty {

lib/AST/Decl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3047,6 +3047,18 @@ bool NominalTypeDecl::isOptionalDecl() const {
30473047
return this == getASTContext().getOptionalDecl();
30483048
}
30493049

3050+
Optional<KeyPathTypeKind> NominalTypeDecl::getKeyPathTypeKind() const {
3051+
auto &ctx = getASTContext();
3052+
#define CASE(NAME) if (this == ctx.get##NAME##Decl()) return KPTK_##NAME;
3053+
CASE(KeyPath)
3054+
CASE(WritableKeyPath)
3055+
CASE(ReferenceWritableKeyPath)
3056+
CASE(AnyKeyPath)
3057+
CASE(PartialKeyPath)
3058+
#undef CASE
3059+
return None;
3060+
}
3061+
30503062
GenericTypeDecl::GenericTypeDecl(DeclKind K, DeclContext *DC,
30513063
Identifier name, SourceLoc nameLoc,
30523064
MutableArrayRef<TypeLoc> inherited,

lib/SILGen/LValue.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class PathComponent {
106106
AddressorKind, // var/subscript addressor
107107
CoroutineAccessorKind, // coroutine accessor
108108
ValueKind, // random base pointer as an lvalue
109-
KeyPathApplicationKind, // applying a key path
109+
PhysicalKeyPathApplicationKind, // applying a key path
110110

111111
// Logical LValue kinds
112112
GetterSetterKind, // property or subscript getter/setter
@@ -115,6 +115,7 @@ class PathComponent {
115115
AutoreleasingWritebackKind, // autorelease pointer on set
116116
WritebackPseudoKind, // a fake component to customize writeback
117117
OpenNonOpaqueExistentialKind, // opened class or metatype existential
118+
LogicalKeyPathApplicationKind, // applying a key path
118119
// Translation LValue kinds (a subtype of logical)
119120
OrigToSubstKind, // generic type substitution
120121
SubstToOrigKind, // generic type substitution

lib/SILGen/SILGenExpr.cpp

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3644,60 +3644,10 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
36443644

36453645
RValue RValueEmitter::
36463646
visitKeyPathApplicationExpr(KeyPathApplicationExpr *E, SGFContext C) {
3647-
// An rvalue key path application always occurs as a read-only projection of
3648-
// the base. The base is received maximally abstracted.
3649-
auto root = SGF.emitMaterializedRValueAsOrig(E->getBase(),
3650-
AbstractionPattern::getOpaque());
3651-
auto keyPath = SGF.emitRValueAsSingleValue(E->getKeyPath());
3652-
3653-
auto keyPathDecl = E->getKeyPath()->getType()->getAnyNominal();
3654-
FuncDecl *projectFn;
3655-
3656-
SmallVector<Type, 2> replacementTypes;
3657-
if (keyPathDecl == SGF.getASTContext().getAnyKeyPathDecl()) {
3658-
// Invoke projectKeyPathAny with the type of the base value.
3659-
// The result is always `Any?`.
3660-
projectFn = SGF.getASTContext().getProjectKeyPathAny(nullptr);
3661-
replacementTypes.push_back(E->getBase()->getType());
3662-
} else {
3663-
auto keyPathTy = E->getKeyPath()->getType()->castTo<BoundGenericType>();
3664-
if (keyPathDecl == SGF.getASTContext().getPartialKeyPathDecl()) {
3665-
// Invoke projectKeyPathPartial with the type of the base value.
3666-
// The result is always `Any`.
3667-
projectFn = SGF.getASTContext().getProjectKeyPathPartial(nullptr);
3668-
replacementTypes.push_back(keyPathTy->getGenericArgs()[0]);
3669-
} else {
3670-
projectFn = SGF.getASTContext().getProjectKeyPathReadOnly(nullptr);
3671-
// Get the root and leaf type from the key path type.
3672-
replacementTypes.push_back(keyPathTy->getGenericArgs()[0]);
3673-
replacementTypes.push_back(keyPathTy->getGenericArgs()[1]);
3674-
3675-
// Upcast the keypath to KeyPath<T, U> if it isn't already.
3676-
if (keyPathTy->getDecl() != SGF.getASTContext().getKeyPathDecl()) {
3677-
auto castToTy = BoundGenericType::get(
3678-
SGF.getASTContext().getKeyPathDecl(),
3679-
nullptr,
3680-
keyPathTy->getGenericArgs())
3681-
->getCanonicalType();
3682-
keyPath = SGF.B.createUpcast(SILLocation(E), keyPath,
3683-
SILType::getPrimitiveObjectType(castToTy));
3684-
}
3685-
}
3686-
}
3687-
3688-
auto projectionGenericSig = projectFn->getGenericSignature();
3689-
auto genericArgsMap = SubstitutionMap::get(
3690-
projectionGenericSig,
3691-
[&](SubstitutableType *type) -> Type {
3692-
auto genericParam = cast<GenericTypeParamType>(type);
3693-
auto index =
3694-
projectionGenericSig->getGenericParamOrdinal(genericParam);
3695-
return replacementTypes[index];
3696-
},
3697-
LookUpConformanceInSignature(*projectionGenericSig));
3647+
FormalEvaluationScope scope(SGF);
36983648

3699-
return SGF.emitApplyOfLibraryIntrinsic(SILLocation(E),
3700-
projectFn, genericArgsMap, {root, keyPath}, C);
3649+
auto lv = SGF.emitLValue(E, SGFAccessKind::OwnedObjectRead);
3650+
return SGF.emitLoadOfLValue(E, std::move(lv), C);
37013651
}
37023652

37033653
RValue RValueEmitter::

0 commit comments

Comments
 (0)