Skip to content

Commit 84167ed

Browse files
committed
[ConstraintSystem] Add a special locator for keypath dynamic member lookup
New locator is going to store pointer to the base keypath declaration. This information is useful to determine whether such keypath is appropriate to access underlying properties/subscripts e.g. `WritableKeyPath` cannot be used to access read-only storage.
1 parent fb30555 commit 84167ed

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

lib/Sema/ConstraintLocator.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
4545
id.AddPointer(elt.getWitness());
4646
break;
4747

48+
case KeyPathDynamicMember:
49+
id.AddPointer(elt.getKeyPath());
50+
break;
51+
4852
case ApplyArgument:
4953
case ApplyFunction:
5054
case FunctionArgument:
@@ -266,6 +270,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
266270
case SynthesizedArgument:
267271
out << " synthesized argument #" << llvm::utostr(elt.getValue());
268272
break;
273+
274+
case KeyPathDynamicMember:
275+
out << " keypath dynamic member lookup";
276+
break;
269277
}
270278
}
271279

lib/Sema/ConstraintLocator.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ class ConstraintLocator : public llvm::FoldingSetNode {
127127
ContextualType,
128128
/// The missing argument synthesized by the solver.
129129
SynthesizedArgument,
130+
/// The member looked up via keypath based dynamic lookup.
131+
KeyPathDynamicMember,
130132
};
131133

132134
/// Determine the number of numeric values used for the given path
@@ -165,6 +167,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
165167
case TupleElement:
166168
case KeyPathComponent:
167169
case SynthesizedArgument:
170+
case KeyPathDynamicMember:
168171
return 1;
169172

170173
case TypeParameterRequirement:
@@ -221,6 +224,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
221224
case DynamicLookupResult:
222225
case ContextualType:
223226
case SynthesizedArgument:
227+
case KeyPathDynamicMember:
224228
return 0;
225229

226230
case FunctionArgument:
@@ -241,6 +245,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
241245
StoredRequirement,
242246
StoredWitness,
243247
StoredGenericSignature,
248+
StoredKeyPathDynamicMemberBase,
244249
StoredKindAndValue
245250
};
246251

@@ -290,6 +295,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
290295
: storage((reinterpret_cast<uintptr_t>(sig) >> 3)),
291296
storedKind(StoredGenericSignature) {}
292297

298+
PathElement(const NominalTypeDecl *keyPath)
299+
: storage((reinterpret_cast<uintptr_t>(keyPath) >> 3)),
300+
storedKind(StoredKeyPathDynamicMemberBase) {}
301+
293302
friend class ConstraintLocator;
294303

295304
public:
@@ -369,6 +378,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
369378
return PathElement(SynthesizedArgument, position);
370379
}
371380

381+
static PathElement getKeyPathDynamicMember(const NominalTypeDecl *base) {
382+
return PathElement(base);
383+
}
384+
372385
/// Retrieve the kind of path element.
373386
PathElementKind getKind() const {
374387
switch (static_cast<StoredKind>(storedKind)) {
@@ -384,6 +397,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
384397
case StoredGenericSignature:
385398
return OpenedGeneric;
386399

400+
case StoredKeyPathDynamicMemberBase:
401+
return KeyPathDynamicMember;
402+
387403
case StoredKindAndValue:
388404
return decodeStorage(storage).first;
389405
}
@@ -443,6 +459,13 @@ class ConstraintLocator : public llvm::FoldingSetNode {
443459
return reinterpret_cast<GenericSignature *>(storage << 3);
444460
}
445461

462+
NominalTypeDecl *getKeyPath() const {
463+
assert((static_cast<StoredKind>(storedKind) ==
464+
StoredKeyPathDynamicMemberBase) &&
465+
"Is not a keypath dynamic member");
466+
return reinterpret_cast<NominalTypeDecl *>(storage << 3);
467+
}
468+
446469
/// Return the summary flags for this particular element.
447470
unsigned getNewSummaryFlags() const {
448471
return getSummaryFlagsForPathElement(getKind());
@@ -459,6 +482,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
459482
bool isSynthesizedArgument() const {
460483
return getKind() == PathElementKind::SynthesizedArgument;
461484
}
485+
486+
bool isKeyPathDynamicMember() const {
487+
return getKind() == PathElementKind::KeyPathDynamicMember;
488+
}
462489
};
463490

464491
/// Return the summary flags for an entire path.

0 commit comments

Comments
 (0)