Skip to content

Commit 28d1466

Browse files
committed
Sema: Add request to synthesize opaque accessors
For now, this just serves to clean up some code; we still eagerly trigger synthesis in the same places as before.
1 parent 112a8d0 commit 28d1466

File tree

6 files changed

+84
-114
lines changed

6 files changed

+84
-114
lines changed

include/swift/AST/Decl.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4397,6 +4397,7 @@ class AbstractStorageDecl : public ValueDecl {
43974397
friend class StorageImplInfoRequest;
43984398
friend class RequiresOpaqueAccessorsRequest;
43994399
friend class RequiresOpaqueModifyCoroutineRequest;
4400+
friend class SynthesizeAccessorRequest;
44004401

44014402
public:
44024403
static const size_t MaxNumAccessors = 255;
@@ -4469,6 +4470,9 @@ class AbstractStorageDecl : public ValueDecl {
44694470
/// The implementation info for the accessors.
44704471
StorageImplInfo ImplInfo;
44714472

4473+
/// Add a synthesized accessor.
4474+
void setSynthesizedAccessor(AccessorKind kind, AccessorDecl *getter);
4475+
44724476
protected:
44734477
AbstractStorageDecl(DeclKind Kind, bool IsStatic, DeclContext *DC,
44744478
DeclName Name, SourceLoc NameLoc,
@@ -4582,6 +4586,12 @@ class AbstractStorageDecl : public ValueDecl {
45824586
return {};
45834587
}
45844588

4589+
/// Return an accessor that this storage is expected to have, synthesizing
4590+
/// one if necessary. Note that will always synthesize one, even if the
4591+
/// accessor is not part of the expected opaque set for the storage, so use
4592+
/// with caution.
4593+
AccessorDecl *getSynthesizedAccessor(AccessorKind kind) const;
4594+
45854595
/// Visit all the opaque accessors that this storage is expected to have.
45864596
void visitExpectedOpaqueAccessors(
45874597
llvm::function_ref<void (AccessorKind)>) const;
@@ -4597,18 +4607,6 @@ class AbstractStorageDecl : public ValueDecl {
45974607
/// This should only be used by the ClangImporter.
45984608
void setComputedSetter(AccessorDecl *Set);
45994609

4600-
/// Add a synthesized getter.
4601-
void setSynthesizedGetter(AccessorDecl *getter);
4602-
4603-
/// Add a synthesized setter.
4604-
void setSynthesizedSetter(AccessorDecl *setter);
4605-
4606-
/// Add a synthesized read coroutine.
4607-
void setSynthesizedReadCoroutine(AccessorDecl *read);
4608-
4609-
/// Add a synthesized modify coroutine.
4610-
void setSynthesizedModifyCoroutine(AccessorDecl *modify);
4611-
46124610
/// Does this storage require opaque accessors of any kind?
46134611
bool requiresOpaqueAccessors() const;
46144612

include/swift/AST/TypeCheckRequests.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,29 @@ class IsAccessorTransparentRequest :
964964
void cacheResult(bool value) const;
965965
};
966966

967+
class SynthesizeAccessorRequest :
968+
public SimpleRequest<SynthesizeAccessorRequest,
969+
AccessorDecl *(AbstractStorageDecl *,
970+
AccessorKind),
971+
CacheKind::SeparatelyCached> {
972+
public:
973+
using SimpleRequest::SimpleRequest;
974+
975+
private:
976+
friend SimpleRequest;
977+
978+
// Evaluation.
979+
llvm::Expected<AccessorDecl *>
980+
evaluate(Evaluator &evaluator, AbstractStorageDecl *decl,
981+
AccessorKind kind) const;
982+
983+
public:
984+
// Separate caching.
985+
bool isCached() const { return true; }
986+
Optional<AccessorDecl *> getCachedResult() const;
987+
void cacheResult(AccessorDecl *value) const;
988+
};
989+
967990
// Allow AnyValue to compare two Type values, even though Type doesn't
968991
// support ==.
969992
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ SWIFT_TYPEID(StorageImplInfoRequest)
5252
SWIFT_TYPEID(RequiresOpaqueAccessorsRequest)
5353
SWIFT_TYPEID(RequiresOpaqueModifyCoroutineRequest)
5454
SWIFT_TYPEID(IsAccessorTransparentRequest)
55+
SWIFT_TYPEID(SynthesizeAccessorRequest)

lib/AST/Decl.cpp

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,6 +1960,16 @@ bool AbstractStorageDecl::requiresOpaqueModifyCoroutine() const {
19601960
false);
19611961
}
19621962

1963+
AccessorDecl *AbstractStorageDecl::getSynthesizedAccessor(AccessorKind kind) const {
1964+
if (auto *accessor = getAccessor(kind))
1965+
return accessor;
1966+
1967+
ASTContext &ctx = getASTContext();
1968+
return evaluateOrDefault(ctx.evaluator,
1969+
SynthesizeAccessorRequest{const_cast<AbstractStorageDecl *>(this), kind},
1970+
nullptr);
1971+
}
1972+
19631973
void AbstractStorageDecl::visitExpectedOpaqueAccessors(
19641974
llvm::function_ref<void (AccessorKind)> visit) const {
19651975
if (!requiresOpaqueAccessors())
@@ -4789,32 +4799,24 @@ AbstractStorageDecl::getSetterFormalAccess() const {
47894799
AccessLevel::Private);
47904800
}
47914801

4792-
#ifndef NDEBUG
4793-
static bool isAccessor(AccessorDecl *accessor, AccessorKind kind,
4794-
AbstractStorageDecl *storage) {
4795-
// TODO: this should check that the accessor belongs to this storage, but
4796-
// the Clang importer currently likes to violate that condition.
4797-
return (accessor && accessor->getAccessorKind() == kind);
4798-
}
4799-
#endif
4800-
48014802
void AbstractStorageDecl::setComputedSetter(AccessorDecl *setter) {
48024803
assert(getImplInfo().getReadImpl() == ReadImplKind::Get);
48034804
assert(!getImplInfo().supportsMutation());
4804-
assert(getGetter() && "sanity check: missing getter");
4805+
assert(getGetter() && "invariant check: missing getter");
48054806
assert(!getSetter() && "already has a setter");
48064807
assert(hasClangNode() && "should only be used for ObjC properties");
4807-
assert(isAccessor(setter, AccessorKind::Set, this));
48084808
assert(setter && "should not be called for readonly properties");
4809+
assert(setter->getAccessorKind() == AccessorKind::Set);
48094810

48104811
setImplInfo(StorageImplInfo::getMutableComputed());
48114812
Accessors.getPointer()->addOpaqueAccessor(setter);
48124813
}
48134814

48144815
void
4815-
AbstractStorageDecl::setSynthesizedGetter(AccessorDecl *accessor) {
4816-
assert(!getGetter() && "declaration doesn't already have getter!");
4817-
assert(isAccessor(accessor, AccessorKind::Get, this));
4816+
AbstractStorageDecl::setSynthesizedAccessor(AccessorKind kind,
4817+
AccessorDecl *accessor) {
4818+
assert(!getAccessor(kind) && "accessor already exists");
4819+
assert(accessor->getAccessorKind() == kind);
48184820

48194821
auto accessors = Accessors.getPointer();
48204822
if (!accessors) {
@@ -4825,42 +4827,6 @@ AbstractStorageDecl::setSynthesizedGetter(AccessorDecl *accessor) {
48254827
accessors->addOpaqueAccessor(accessor);
48264828
}
48274829

4828-
void
4829-
AbstractStorageDecl::setSynthesizedReadCoroutine(AccessorDecl *accessor) {
4830-
assert(!getReadCoroutine() && "already has a read accessor");
4831-
assert(isAccessor(accessor, AccessorKind::Read, this));
4832-
4833-
auto accessors = Accessors.getPointer();
4834-
if (!accessors) {
4835-
accessors = AccessorRecord::create(getASTContext(), SourceRange(), {});
4836-
Accessors.setPointer(accessors);
4837-
}
4838-
4839-
accessors->addOpaqueAccessor(accessor);
4840-
}
4841-
4842-
void
4843-
AbstractStorageDecl::setSynthesizedSetter(AccessorDecl *accessor) {
4844-
assert((getGetter() || getReadCoroutine()) &&
4845-
"declaration doesn't already have getter!");
4846-
assert(supportsMutation() && "adding setter to immutable storage");
4847-
assert(isAccessor(accessor, AccessorKind::Set, this));
4848-
4849-
Accessors.getPointer()->addOpaqueAccessor(accessor);
4850-
}
4851-
4852-
void
4853-
AbstractStorageDecl::setSynthesizedModifyCoroutine(AccessorDecl *accessor) {
4854-
assert((getGetter() || getReadCoroutine()) &&
4855-
"declaration doesn't already have getter!");
4856-
assert(getSetter() && "declaration doesn't already have setter!");
4857-
assert(supportsMutation() && "adding modify to immutable storage");
4858-
assert(!getModifyCoroutine() && "already has a modify accessor");
4859-
assert(isAccessor(accessor, AccessorKind::Modify, this));
4860-
4861-
Accessors.getPointer()->addOpaqueAccessor(accessor);
4862-
}
4863-
48644830
static Optional<ObjCSelector>
48654831
getNameFromObjcAttribute(const ObjCAttr *attr, DeclName preferredName) {
48664832
if (!attr)

lib/AST/TypeCheckRequests.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,3 +764,24 @@ void IsAccessorTransparentRequest::cacheResult(bool value) const {
764764
}
765765
}
766766
}
767+
768+
//----------------------------------------------------------------------------//
769+
// SynthesizeAccessorRequest computation.
770+
//----------------------------------------------------------------------------//
771+
772+
Optional<AccessorDecl *>
773+
SynthesizeAccessorRequest::getCachedResult() const {
774+
auto *storage = std::get<0>(getStorage());
775+
auto kind = std::get<1>(getStorage());
776+
auto *accessor = storage->getAccessor(kind);
777+
if (accessor)
778+
return accessor;
779+
return None;
780+
}
781+
782+
void SynthesizeAccessorRequest::cacheResult(AccessorDecl *accessor) const {
783+
auto *storage = std::get<0>(getStorage());
784+
auto kind = std::get<1>(getStorage());
785+
786+
storage->setSynthesizedAccessor(kind, accessor);
787+
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,54 +1266,24 @@ synthesizeModifyCoroutineBody(AccessorDecl *modify, ASTContext &ctx) {
12661266
return synthesizeCoroutineAccessorBody(modify, ctx);
12671267
}
12681268

1269-
static void addGetterToStorage(AbstractStorageDecl *storage,
1270-
ASTContext &ctx) {
1271-
auto getter = createGetterPrototype(storage, ctx);
1272-
1273-
// Install the prototype.
1274-
storage->setSynthesizedGetter(getter);
1275-
}
1276-
1277-
static void addSetterToStorage(AbstractStorageDecl *storage,
1278-
ASTContext &ctx) {
1279-
auto setter = createSetterPrototype(storage, ctx);
1280-
1281-
// Install the prototype.
1282-
storage->setSynthesizedSetter(setter);
1283-
}
1284-
1285-
static void addReadCoroutineToStorage(AbstractStorageDecl *storage,
1286-
ASTContext &ctx) {
1287-
auto read = createReadCoroutinePrototype(storage, ctx);
1288-
1289-
// Install the prototype.
1290-
storage->setSynthesizedReadCoroutine(read);
1291-
}
1292-
1293-
static void addModifyCoroutineToStorage(AbstractStorageDecl *storage,
1294-
ASTContext &ctx) {
1295-
auto modify = createModifyCoroutinePrototype(storage, ctx);
1296-
1297-
// Install the prototype.
1298-
storage->setSynthesizedModifyCoroutine(modify);
1299-
}
1300-
1269+
llvm::Expected<AccessorDecl *>
1270+
SynthesizeAccessorRequest::evaluate(Evaluator &evaluator,
1271+
AbstractStorageDecl *storage,
1272+
AccessorKind kind) const {
1273+
auto &ctx = storage->getASTContext();
13011274

1302-
static void addOpaqueAccessorToStorage(AbstractStorageDecl *storage,
1303-
AccessorKind kind,
1304-
ASTContext &ctx) {
13051275
switch (kind) {
13061276
case AccessorKind::Get:
1307-
return addGetterToStorage(storage, ctx);
1277+
return createGetterPrototype(storage, ctx);
13081278

13091279
case AccessorKind::Set:
1310-
return addSetterToStorage(storage, ctx);
1280+
return createSetterPrototype(storage, ctx);
13111281

13121282
case AccessorKind::Read:
1313-
return addReadCoroutineToStorage(storage, ctx);
1283+
return createReadCoroutinePrototype(storage, ctx);
13141284

13151285
case AccessorKind::Modify:
1316-
return addModifyCoroutineToStorage(storage, ctx);
1286+
return createModifyCoroutinePrototype(storage, ctx);
13171287

13181288
#define OPAQUE_ACCESSOR(ID, KEYWORD)
13191289
#define ACCESSOR(ID) \
@@ -1324,14 +1294,9 @@ static void addOpaqueAccessorToStorage(AbstractStorageDecl *storage,
13241294
}
13251295

13261296
void swift::addExpectedOpaqueAccessorsToStorage(AbstractStorageDecl *storage) {
1327-
auto &ctx = storage->getASTContext();
1328-
13291297
storage->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1330-
// If the accessor is already present, there's nothing to do.
1331-
if (storage->getAccessor(kind))
1332-
return;
1333-
1334-
addOpaqueAccessorToStorage(storage, kind, ctx);
1298+
// Force synthesis if necessary.
1299+
(void) storage->getSynthesizedAccessor(kind);
13351300
});
13361301
}
13371302

@@ -1366,12 +1331,8 @@ void TypeChecker::synthesizeWitnessAccessorsForStorage(
13661331
DeclsToFinalize.insert(requirement);
13671332

13681333
requirement->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1369-
// If the accessor already exists, we have nothing to do.
1370-
if (storage->getAccessor(kind))
1371-
return;
1372-
1373-
// Otherwise, synthesize it.
1374-
addOpaqueAccessorToStorage(storage, kind, Context);
1334+
// Force synthesis if necessary.
1335+
(void) storage->getSynthesizedAccessor(kind);
13751336
});
13761337
}
13771338

0 commit comments

Comments
 (0)