Skip to content

Commit b60f4ed

Browse files
authored
Merge pull request #26469 from slavapestov/lazy-accessor-synthesis-part-2
Lazy accessor synthesis for storage in primary files
2 parents ff7aeaf + 05baaa8 commit b60f4ed

21 files changed

+130
-103
lines changed

include/swift/AST/Decl.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4565,10 +4565,9 @@ class AbstractStorageDecl : public ValueDecl {
45654565
bool isSettable(const DeclContext *UseDC,
45664566
const DeclRefExpr *base = nullptr) const;
45674567

4568-
/// Are there any accessors for this declaration, including implicit ones?
4569-
bool hasAnyAccessors() const {
4570-
return !getAllAccessors().empty();
4571-
}
4568+
/// Does this storage declaration have explicitly-defined accessors
4569+
/// written in the source?
4570+
bool hasParsedAccessors() const;
45724571

45734572
/// Return the ownership of values opaquely read from this storage.
45744573
OpaqueReadOwnership getOpaqueReadOwnership() const;
@@ -4628,13 +4627,21 @@ class AbstractStorageDecl : public ValueDecl {
46284627
/// accessor was not explicitly defined by the user.
46294628
AccessorDecl *getParsedAccessor(AccessorKind kind) const;
46304629

4631-
/// Visit all the opaque accessors that this storage is expected to have.
4630+
/// Visit all parsed accessors.
4631+
void visitParsedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
4632+
4633+
/// Visit all opaque accessor kinds.
46324634
void visitExpectedOpaqueAccessors(
46334635
llvm::function_ref<void (AccessorKind)>) const;
46344636

4635-
/// Visit all the opaque accessors of this storage declaration.
4637+
/// Visit all opaque accessors.
46364638
void visitOpaqueAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
46374639

4640+
/// Visit all eagerly emitted accessors.
4641+
///
4642+
/// This is the union of the parsed and opaque sets.
4643+
void visitEmittedAccessors(llvm::function_ref<void (AccessorDecl*)>) const;
4644+
46384645
void setAccessors(SourceLoc lbraceLoc, ArrayRef<AccessorDecl*> accessors,
46394646
SourceLoc rbraceLoc);
46404647

lib/AST/ASTMangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ExistentialLayout.h"
2121
#include "swift/AST/GenericSignature.h"
2222
#include "swift/AST/Initializer.h"
23+
#include "swift/AST/LazyResolver.h"
2324
#include "swift/AST/Module.h"
2425
#include "swift/AST/Ownership.h"
2526
#include "swift/AST/ParameterList.h"
@@ -2323,6 +2324,12 @@ CanType ASTMangler::getDeclTypeForMangling(
23232324
parentGenericSig = nullptr;
23242325

23252326
auto &C = decl->getASTContext();
2327+
if (!decl->hasInterfaceType() && !decl->getDeclContext()->isLocalContext()) {
2328+
if (auto *resolver = C.getLazyResolver()) {
2329+
resolver->resolveDeclSignature(const_cast<ValueDecl *>(decl));
2330+
}
2331+
}
2332+
23262333
if (!decl->hasInterfaceType() || decl->getInterfaceType()->is<ErrorType>()) {
23272334
if (isa<AbstractFunctionDecl>(decl))
23282335
return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)},

lib/AST/ASTScopeCreation.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,8 @@ ASTScopeImpl *ScopeCreator::createScopeFor(ASTNode n, ASTScopeImpl *parent) {
516516

517517
void ScopeCreator::addChildrenForAllExplicitAccessors(AbstractStorageDecl *asd,
518518
ASTScopeImpl *parent) {
519-
for (auto accessor : asd->getAllAccessors()) {
520-
if (!accessor->isImplicit() && accessor->getStartLoc().isValid()) {
519+
asd->visitParsedAccessors([&](AccessorDecl *accessor) {
520+
if (accessor->getStartLoc().isValid()) {
521521
// Accessors are always nested within their abstract storage
522522
// declaration. The nesting may not be immediate, because subscripts may
523523
// have intervening scopes for generics.
@@ -526,7 +526,7 @@ void ScopeCreator::addChildrenForAllExplicitAccessors(AbstractStorageDecl *asd,
526526
ASTVisitorForScopeCreation().visitAbstractFunctionDecl(accessor, parent,
527527
*this);
528528
}
529-
}
529+
});
530530
}
531531

532532
#pragma mark creation helpers

lib/AST/Decl.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,13 @@ AccessorDecl *AbstractStorageDecl::getOpaqueAccessor(AccessorKind kind) const {
20102010
return getSynthesizedAccessor(kind);
20112011
}
20122012

2013+
bool AbstractStorageDecl::hasParsedAccessors() const {
2014+
for (auto *accessor : getAllAccessors())
2015+
if (!accessor->isImplicit())
2016+
return true;
2017+
return false;
2018+
}
2019+
20132020
AccessorDecl *AbstractStorageDecl::getParsedAccessor(AccessorKind kind) const {
20142021
auto *accessor = getAccessor(kind);
20152022
if (accessor && !accessor->isImplicit())
@@ -2018,6 +2025,22 @@ AccessorDecl *AbstractStorageDecl::getParsedAccessor(AccessorKind kind) const {
20182025
return nullptr;
20192026
}
20202027

2028+
void AbstractStorageDecl::visitParsedAccessors(
2029+
llvm::function_ref<void (AccessorDecl*)> visit) const {
2030+
for (auto *accessor : getAllAccessors())
2031+
if (!accessor->isImplicit())
2032+
visit(accessor);
2033+
}
2034+
2035+
void AbstractStorageDecl::visitEmittedAccessors(
2036+
llvm::function_ref<void (AccessorDecl*)> visit) const {
2037+
visitParsedAccessors(visit);
2038+
visitOpaqueAccessors([&](AccessorDecl *accessor) {
2039+
if (accessor->isImplicit())
2040+
visit(accessor);
2041+
});
2042+
}
2043+
20212044
void AbstractStorageDecl::visitExpectedOpaqueAccessors(
20222045
llvm::function_ref<void (AccessorKind)> visit) const {
20232046
if (!requiresOpaqueAccessors())
@@ -6440,13 +6463,6 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
64406463

64416464
auto &ctx = dc->getASTContext();
64426465

6443-
// FIXME: Remove this once getInterfaceType(), isDesignatedInit() and
6444-
// anything else that is used below has been request-ified.
6445-
if (!decl->hasInterfaceType()) {
6446-
ctx.getLazyResolver()->resolveDeclSignature(
6447-
const_cast<AbstractFunctionDecl *>(decl));
6448-
}
6449-
64506466
// Initializers are not normally inherited, but required initializers can
64516467
// be overridden for invocation from dynamic types, and convenience initializers
64526468
// are conditionally inherited when all designated initializers are available,
@@ -6471,13 +6487,6 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
64716487
if (!base || base->hasClangNode() || base->isObjCDynamic())
64726488
return true;
64736489

6474-
// FIXME: Remove this once getInterfaceType(), isDesignatedInit() and
6475-
// anything else that is used below has been request-ified.
6476-
if (!base->hasInterfaceType()) {
6477-
ctx.getLazyResolver()->resolveDeclSignature(
6478-
const_cast<AbstractFunctionDecl *>(base));
6479-
}
6480-
64816490
// As above, convenience initializers are not formally overridable in Swift
64826491
// vtables, although same-named initializers are modeled as overriding for
64836492
// various QoI and objc interop reasons. Even if we "override" a non-required
@@ -6494,6 +6503,17 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
64946503
if (decl->isEffectiveLinkageMoreVisibleThan(base))
64956504
return true;
64966505

6506+
// FIXME: Remove this once getInterfaceType() has been request-ified.
6507+
if (!decl->hasInterfaceType()) {
6508+
ctx.getLazyResolver()->resolveDeclSignature(
6509+
const_cast<AbstractFunctionDecl *>(decl));
6510+
}
6511+
6512+
if (!base->hasInterfaceType()) {
6513+
ctx.getLazyResolver()->resolveDeclSignature(
6514+
const_cast<AbstractFunctionDecl *>(base));
6515+
}
6516+
64976517
// If the method overrides something, we only need a new entry if the
64986518
// override has a more general AST type. However an abstraction
64996519
// change is OK; we don't want to add a whole new vtable entry just

lib/IDE/Refactoring.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,8 +1618,9 @@ class FindAllSubDecls : public SourceEntityWalker {
16181618
return false;
16191619

16201620
if (auto ASD = dyn_cast<AbstractStorageDecl>(D)) {
1621-
auto accessors = ASD->getAllAccessors();
1622-
Found.insert(accessors.begin(), accessors.end());
1621+
ASD->visitParsedAccessors([&](AccessorDecl *accessor) {
1622+
Found.insert(accessor);
1623+
});
16231624
}
16241625
return true;
16251626
}

lib/Index/Index.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,15 +1103,13 @@ bool IndexSwiftASTWalker::report(ValueDecl *D) {
11031103
// Even if we don't record a local property we still need to walk its
11041104
// accessor bodies.
11051105
if (auto StoreD = dyn_cast<AbstractStorageDecl>(D)) {
1106-
for (auto accessor : StoreD->getAllAccessors()) {
1107-
if (accessor->isImplicit())
1108-
continue;
1106+
StoreD->visitParsedAccessors([&](AccessorDecl *accessor) {
1107+
if (Cancelled)
1108+
return;
11091109
ManuallyVisitedAccessorStack.push_back(accessor);
11101110
SourceEntityWalker::walk(cast<Decl>(accessor));
11111111
ManuallyVisitedAccessorStack.pop_back();
1112-
if (Cancelled)
1113-
return false;
1114-
}
1112+
});
11151113
}
11161114
}
11171115

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,15 +1328,15 @@ void SILGenModule::visitVarDecl(VarDecl *vd) {
13281328
if (vd->hasStorage())
13291329
addGlobalVariable(vd);
13301330

1331-
for (auto *accessor : vd->getAllAccessors())
1331+
vd->visitEmittedAccessors([&](AccessorDecl *accessor) {
13321332
emitFunction(accessor);
1333+
});
13331334

13341335
tryEmitPropertyDescriptor(vd);
13351336
}
13361337

13371338
void SILGenModule::visitSubscriptDecl(SubscriptDecl *sd) {
1338-
for (auto *accessor : sd->getAllAccessors())
1339-
emitFunction(accessor);
1339+
llvm_unreachable("top-level subscript?");
13401340
}
13411341

13421342
bool

lib/SILGen/SILGenDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1194,8 +1194,9 @@ void SILGenFunction::visitVarDecl(VarDecl *D) {
11941194
// We handle emitting the variable storage when we see the pattern binding.
11951195

11961196
// Emit the variable's accessors.
1197-
for (auto *accessor : D->getAllAccessors())
1197+
D->visitEmittedAccessors([&](AccessorDecl *accessor) {
11981198
SGM.emitFunction(accessor);
1199+
});
11991200
}
12001201

12011202
/// Emit literals for the major, minor, and subminor components of the version

lib/SILGen/SILGenExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3360,7 +3360,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
33603360
// storage.
33613361
// Properties that are not public don't need property descriptors
33623362
// either.
3363-
(!baseDecl->hasAnyAccessors() ||
3363+
(!baseDecl->requiresOpaqueAccessors() ||
33643364
(!getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))
33653365
.isForeign &&
33663366
getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))

lib/SILGen/SILGenType.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,9 +1050,9 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
10501050
}
10511051

10521052
void visitAccessors(AbstractStorageDecl *asd) {
1053-
for (auto *accessor : asd->getAllAccessors())
1054-
if (!accessor->hasForcedStaticDispatch())
1055-
visitFuncDecl(accessor);
1053+
asd->visitEmittedAccessors([&](AccessorDecl *accessor) {
1054+
visitFuncDecl(accessor);
1055+
});
10561056
}
10571057
};
10581058

@@ -1182,9 +1182,9 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
11821182
}
11831183

11841184
void visitAccessors(AbstractStorageDecl *asd) {
1185-
for (auto *accessor : asd->getAllAccessors())
1186-
if (!accessor->hasForcedStaticDispatch())
1187-
visitFuncDecl(accessor);
1185+
asd->visitEmittedAccessors([&](AccessorDecl *accessor) {
1186+
visitFuncDecl(accessor);
1187+
});
11881188
}
11891189
};
11901190

lib/Sema/CSApply.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4039,7 +4039,6 @@ namespace {
40394039
method = func;
40404040
} else if (auto var = dyn_cast<VarDecl>(foundDecl)) {
40414041
// Properties.
4042-
addExpectedOpaqueAccessorsToStorage(var);
40434042

40444043
// If this isn't a property on a type, complain.
40454044
if (!var->getDeclContext()->isTypeContext()) {

lib/Sema/CodeSynthesis.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,13 +1293,6 @@ SynthesizeAccessorRequest::evaluate(Evaluator &evaluator,
12931293
}
12941294
}
12951295

1296-
void swift::addExpectedOpaqueAccessorsToStorage(AbstractStorageDecl *storage) {
1297-
storage->visitExpectedOpaqueAccessors([&](AccessorKind kind) {
1298-
// Force synthesis if necessary.
1299-
(void) storage->getSynthesizedAccessor(kind);
1300-
});
1301-
}
1302-
13031296
/// Synthesize the body of a setter which just delegates to a mutable
13041297
/// addressor.
13051298
static std::pair<BraceStmt *, bool>
@@ -1717,7 +1710,6 @@ static VarDecl *synthesizePropertyWrapperStorageWrapperProperty(
17171710
property->setImplInfo(StorageImplInfo::getMutableComputed());
17181711
else
17191712
property->setImplInfo(StorageImplInfo::getImmutableComputed());
1720-
addExpectedOpaqueAccessorsToStorage(property);
17211713

17221714
var->getAttrs().add(
17231715
new (ctx) ProjectedValuePropertyAttr(name, SourceLoc(), SourceRange(),

lib/Sema/CodeSynthesis.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class ObjCReason;
4545
// Implemented in TypeCheckerOverride.cpp
4646
bool checkOverrides(ValueDecl *decl);
4747

48-
// These are implemented in CodeSynthesis.cpp.
49-
void addExpectedOpaqueAccessorsToStorage(AbstractStorageDecl *storage);
50-
5148
/// Describes the kind of implicit constructor that will be
5249
/// generated.
5350
enum class ImplicitConstructorKind {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,23 +2140,24 @@ static FuncDecl *findReplacedAccessor(DeclName replacedVarName,
21402140
}
21412141

21422142
// Find the accessor in the replaced storage decl.
2143-
for (auto *origAccessor : origStorage->getAllAccessors()) {
2144-
TC.validateDecl(origAccessor);
2145-
if (origAccessor->getAccessorKind() != replacement->getAccessorKind())
2146-
continue;
2143+
auto *origAccessor = origStorage->getOpaqueAccessor(
2144+
replacement->getAccessorKind());
2145+
if (!origAccessor)
2146+
return nullptr;
21472147

2148-
if (origAccessor->isImplicit() &&
2149-
!(origStorage->getReadImpl() == ReadImplKind::Stored &&
2150-
origStorage->getWriteImpl() == WriteImplKind::Stored)) {
2151-
TC.diagnose(attr->getLocation(),
2152-
diag::dynamic_replacement_accessor_not_explicit,
2153-
(unsigned)origAccessor->getAccessorKind(), replacedVarName);
2154-
attr->setInvalid();
2155-
return nullptr;
2156-
}
2157-
return origAccessor;
2148+
TC.validateDecl(origAccessor);
2149+
2150+
if (origAccessor->isImplicit() &&
2151+
!(origStorage->getReadImpl() == ReadImplKind::Stored &&
2152+
origStorage->getWriteImpl() == WriteImplKind::Stored)) {
2153+
TC.diagnose(attr->getLocation(),
2154+
diag::dynamic_replacement_accessor_not_explicit,
2155+
(unsigned)origAccessor->getAccessorKind(), replacedVarName);
2156+
attr->setInvalid();
2157+
return nullptr;
21582158
}
2159-
return nullptr;
2159+
2160+
return origAccessor;
21602161
}
21612162

21622163
static AbstractFunctionDecl *
@@ -2298,19 +2299,19 @@ void TypeChecker::checkDynamicReplacementAttribute(ValueDecl *D) {
22982299

22992300
// Collect the accessor replacement mapping if this is an abstract storage.
23002301
if (auto *var = dyn_cast<AbstractStorageDecl>(D)) {
2301-
for (auto *accessor : var->getAllAccessors()) {
2302+
var->visitParsedAccessors([&](AccessorDecl *accessor) {
2303+
if (attr->isInvalid())
2304+
return;
2305+
23022306
validateDecl(accessor);
2303-
if (accessor->isImplicit())
2304-
continue;
23052307
auto *orig = findReplacedAccessor(attr->getReplacedFunctionName(),
23062308
accessor, attr, *this);
2307-
if (attr->isInvalid())
2308-
return;
23092309
if (!orig)
2310-
continue;
2310+
return;
2311+
23112312
origs.push_back(orig);
23122313
replacements.push_back(accessor);
2313-
}
2314+
});
23142315
} else {
23152316
// Otherwise, find the matching function.
23162317
auto *fun = cast<AbstractFunctionDecl>(D);
@@ -2823,12 +2824,14 @@ void TypeChecker::addImplicitDynamicAttribute(Decl *D) {
28232824
return;
28242825
}
28252826

2826-
// Don't add dynamic if accessor is inlinable or tranparent.
2827+
// Don't add dynamic if accessor is inlinable or transparent.
28272828
if (auto *asd = dyn_cast<AbstractStorageDecl>(D)) {
2828-
for (auto *accessor : asd->getAllAccessors()) {
2829-
if (!accessor->isImplicit() && shouldBlockImplicitDynamic(accessor))
2830-
return;
2831-
}
2829+
bool blocked = false;
2830+
asd->visitParsedAccessors([&](AccessorDecl *accessor) {
2831+
blocked |= shouldBlockImplicitDynamic(accessor);
2832+
});
2833+
if (blocked)
2834+
return;
28322835
}
28332836

28342837
if (auto *VD = dyn_cast<VarDecl>(D)) {

0 commit comments

Comments
 (0)