Skip to content

Commit d9fd3d3

Browse files
authored
Merge pull request #26356 from slavapestov/accessors-are-not-members
Stop adding accessors to their parent DeclContext
2 parents 74803f0 + 1ee2db4 commit d9fd3d3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+480
-394
lines changed

include/swift/AST/ASTWalker.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ class ASTWalker {
221221
/// bodies of closures that have not yet been type checked.
222222
virtual bool shouldWalkIntoNonSingleExpressionClosure() { return true; }
223223

224+
/// This method configures whether the walker should exhibit the legacy
225+
/// behavior where accessors appear as peers of their storage, rather
226+
/// than children nested inside of it.
227+
///
228+
/// Please don't write new ASTWalker implementations that override this
229+
/// method to return true; instead, refactor existing code as needed
230+
/// until eventually we can remove this altogether.
231+
virtual bool shouldWalkAccessorsTheOldWay() { return false; }
232+
224233
/// walkToParameterListPre - This method is called when first visiting a
225234
/// ParameterList, before walking into its parameters. If it returns false,
226235
/// the subtree is skipped.

include/swift/AST/Decl.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5853,10 +5853,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
58535853
return cast_or_null<AbstractFunctionDecl>(ValueDecl::getOverriddenDecl());
58545854
}
58555855

5856-
/// Returns true if a function declaration overrides a given
5857-
/// method from its direct or indirect superclass.
5858-
bool isOverridingDecl(const AbstractFunctionDecl *method) const;
5859-
58605856
/// Whether the declaration is later overridden in the module
58615857
///
58625858
/// Overrides are resolved during type checking; only query this field after
@@ -7041,22 +7037,14 @@ class MissingMemberDecl : public Decl {
70417037
}
70427038
public:
70437039
static MissingMemberDecl *
7044-
forMethod(ASTContext &ctx, DeclContext *DC, DeclName name,
7045-
bool hasNormalVTableEntry) {
7046-
assert(!name || name.isCompoundName());
7047-
return new (ctx) MissingMemberDecl(DC, name, hasNormalVTableEntry, 0);
7048-
}
7049-
7050-
static MissingMemberDecl *
7051-
forInitializer(ASTContext &ctx, DeclContext *DC, DeclName name,
7052-
bool hasVTableEntry) {
7053-
unsigned entries = hasVTableEntry ? 1 : 0;
7054-
return new (ctx) MissingMemberDecl(DC, name, entries, 0);
7055-
}
7056-
7057-
static MissingMemberDecl *
7058-
forStoredProperty(ASTContext &ctx, DeclContext *DC, DeclName name) {
7059-
return new (ctx) MissingMemberDecl(DC, name, 0, 1);
7040+
create(ASTContext &ctx, DeclContext *DC, DeclName name,
7041+
unsigned numVTableEntries, bool hasStorage) {
7042+
assert(!numVTableEntries || isa<ProtocolDecl>(DC) || isa<ClassDecl>(DC) &&
7043+
"Only classes and protocols have vtable/witness table entries");
7044+
assert(!hasStorage || !isa<ProtocolDecl>(DC) &&
7045+
"Protocols cannot have missing stored properties");
7046+
7047+
return new (ctx) MissingMemberDecl(DC, name, numVTableEntries, hasStorage);
70607048
}
70617049

70627050
DeclName getFullName() const {

include/swift/IDE/Utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,8 @@ class NameMatcher: public ASTWalker {
275275
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override;
276276
bool shouldWalkIntoGenericParams() override { return true; }
277277

278+
// FIXME: Remove this
279+
bool shouldWalkAccessorsTheOldWay() override { return true; }
278280

279281
public:
280282
explicit NameMatcher(SourceFile &SrcFile) : SrcFile(SrcFile) { }

include/swift/SIL/SILVTableVisitor.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ template <class T> class SILVTableVisitor {
9999
maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Allocator));
100100
}
101101

102+
void maybeAddAccessors(AbstractStorageDecl *asd) {
103+
// FIXME: This should not be necessary once visitOpaqueAccessors()
104+
// incorporates the logic currently in maybeAddAccessorsToStorage().
105+
if (!asd->hasAnyAccessors())
106+
return;
107+
108+
asd->visitOpaqueAccessors([&](AccessorDecl *accessor) {
109+
maybeAddMethod(accessor);
110+
});
111+
}
112+
102113
void maybeAddEntry(SILDeclRef declRef) {
103114
// Introduce a new entry if required.
104115
if (declRef.requiresNewVTableEntry())
@@ -134,10 +145,14 @@ template <class T> class SILVTableVisitor {
134145
}
135146

136147
void maybeAddMember(Decl *member) {
137-
if (auto *fd = dyn_cast<FuncDecl>(member))
148+
if (auto *ad = dyn_cast<AccessorDecl>(member))
149+
/* handled as part of its storage */;
150+
else if (auto *fd = dyn_cast<FuncDecl>(member))
138151
maybeAddMethod(fd);
139152
else if (auto *cd = dyn_cast<ConstructorDecl>(member))
140153
maybeAddConstructor(cd);
154+
else if (auto *asd = dyn_cast<AbstractStorageDecl>(member))
155+
maybeAddAccessors(asd);
141156
else if (auto *placeholder = dyn_cast<MissingMemberDecl>(member))
142157
asDerived().addPlaceholder(placeholder);
143158
}

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 504; // distinguish implicit raw values for enum cases
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 505; // track vtable entries for storage
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1064,6 +1064,7 @@ namespace decls_block {
10641064
AccessLevelField, // setter access, if applicable
10651065
DeclIDField, // opaque return type decl
10661066
BCFixed<2>, // # of property wrapper backing properties
1067+
BCVBR<4>, // total number of vtable entries introduced by all accessors
10671068
BCArray<TypeIDField> // accessors, backing properties, and dependencies
10681069
>;
10691070

@@ -1224,6 +1225,7 @@ namespace decls_block {
12241225
StaticSpellingKindField, // is subscript static?
12251226
BCVBR<5>, // number of parameter name components
12261227
DeclIDField, // opaque return type decl
1228+
BCFixed<8>, // total number of vtable entries introduced by all accessors
12271229
BCArray<IdentifierIDField> // name components,
12281230
// followed by DeclID accessors,
12291231
// followed by TypeID dependencies

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,6 +3179,12 @@ void PrintAST::visitModuleDecl(ModuleDecl *decl) { }
31793179
void PrintAST::visitMissingMemberDecl(MissingMemberDecl *decl) {
31803180
Printer << "/* placeholder for ";
31813181
recordDeclLoc(decl, [&]{ Printer << decl->getFullName(); });
3182+
unsigned numVTableEntries = decl->getNumberOfVTableEntries();
3183+
if (numVTableEntries > 0)
3184+
Printer << " (vtable entries: " << numVTableEntries << ")";
3185+
unsigned numFieldOffsetVectorEntries = decl->getNumberOfFieldOffsetVectorEntries();
3186+
if (numFieldOffsetVectorEntries > 0)
3187+
Printer << " (field offsets: " << numFieldOffsetVectorEntries << ")";
31823188
Printer << " */";
31833189
}
31843190

lib/AST/ASTWalker.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,19 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
146146
for (Decl *M : ED->getMembers()) {
147147
if (doIt(M))
148148
return true;
149+
150+
if (Walker.shouldWalkAccessorsTheOldWay()) {
151+
// Pretend that accessors share a parent with the storage.
152+
//
153+
// FIXME: Update existing ASTWalkers to deal with accessors appearing as
154+
// children of the storage instead.
155+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(M)) {
156+
for (auto AD : ASD->getAllAccessors()) {
157+
if (doIt(AD))
158+
return true;
159+
}
160+
}
161+
}
149162
}
150163
return false;
151164
}
@@ -277,9 +290,23 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
277290
}
278291
}
279292

280-
for (Decl *Member : NTD->getMembers())
293+
for (Decl *Member : NTD->getMembers()) {
281294
if (doIt(Member))
282295
return true;
296+
297+
if (Walker.shouldWalkAccessorsTheOldWay()) {
298+
// Pretend that accessors share a parent with the storage.
299+
//
300+
// FIXME: Update existing ASTWalkers to deal with accessors appearing as
301+
// children of the storage instead.
302+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(Member)) {
303+
for (auto AD : ASD->getAllAccessors()) {
304+
if (doIt(AD))
305+
return true;
306+
}
307+
}
308+
}
309+
}
283310
return false;
284311
}
285312

@@ -289,6 +316,12 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
289316
}
290317

291318
bool visitVarDecl(VarDecl *VD) {
319+
if (!Walker.shouldWalkAccessorsTheOldWay()) {
320+
for (auto *AD : VD->getAllAccessors())
321+
if (doIt(AD))
322+
return true;
323+
}
324+
292325
return false;
293326
}
294327

@@ -309,6 +342,13 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
309342
return true;
310343
}
311344
}
345+
346+
if (!Walker.shouldWalkAccessorsTheOldWay()) {
347+
for (auto *AD : SD->getAllAccessors())
348+
if (doIt(AD))
349+
return true;
350+
}
351+
312352
return false;
313353
}
314354

@@ -1353,8 +1393,22 @@ Stmt *Traversal::visitBraceStmt(BraceStmt *BS) {
13531393
continue;
13541394
}
13551395

1356-
if (doIt(Elem.get<Decl*>()))
1396+
auto *D = Elem.get<Decl*>();
1397+
if (doIt(D))
13571398
return nullptr;
1399+
1400+
if (Walker.shouldWalkAccessorsTheOldWay()) {
1401+
// Pretend that accessors share a parent with the storage.
1402+
//
1403+
// FIXME: Update existing ASTWalkers to deal with accessors appearing as
1404+
// children of the storage instead.
1405+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
1406+
for (auto AD : ASD->getAllAccessors()) {
1407+
if (doIt(AD))
1408+
return nullptr;
1409+
}
1410+
}
1411+
}
13581412
}
13591413

13601414
return BS;

lib/AST/Decl.cpp

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3998,47 +3998,56 @@ ArtificialMainKind ClassDecl::getArtificialMainKind() const {
39983998
llvm_unreachable("class has no @ApplicationMain attr?!");
39993999
}
40004000

4001-
AbstractFunctionDecl *
4002-
ClassDecl::findOverridingDecl(const AbstractFunctionDecl *Method) const {
4003-
auto Members = getMembers();
4004-
for (auto M : Members) {
4005-
auto *CurMethod = dyn_cast<AbstractFunctionDecl>(M);
4006-
if (!CurMethod)
4007-
continue;
4008-
if (CurMethod->isOverridingDecl(Method)) {
4009-
return CurMethod;
4010-
}
4001+
static bool isOverridingDecl(const ValueDecl *Derived,
4002+
const ValueDecl *Base) {
4003+
while (Derived) {
4004+
if (Derived == Base)
4005+
return true;
4006+
Derived = Derived->getOverriddenDecl();
4007+
}
4008+
return false;
4009+
}
4010+
4011+
static ValueDecl *findOverridingDecl(const ClassDecl *C,
4012+
const ValueDecl *Base) {
4013+
// FIXME: This is extremely inefficient. The SILOptimizer should build a
4014+
// reverse lookup table to answer these types of queries.
4015+
for (auto M : C->getMembers()) {
4016+
if (auto *Derived = dyn_cast<ValueDecl>(M))
4017+
if (::isOverridingDecl(Derived, Base))
4018+
return Derived;
40114019
}
4020+
40124021
return nullptr;
40134022
}
40144023

4015-
bool AbstractFunctionDecl::isOverridingDecl(
4016-
const AbstractFunctionDecl *Method) const {
4017-
const AbstractFunctionDecl *CurMethod = this;
4018-
while (CurMethod) {
4019-
if (CurMethod == Method)
4020-
return true;
4021-
CurMethod = CurMethod->getOverriddenDecl();
4024+
AbstractFunctionDecl *
4025+
ClassDecl::findOverridingDecl(const AbstractFunctionDecl *Method) const {
4026+
if (auto *Accessor = dyn_cast<AccessorDecl>(Method)) {
4027+
auto *Storage = Accessor->getStorage();
4028+
if (auto *Derived = ::findOverridingDecl(this, Storage)) {
4029+
auto *DerivedStorage = cast<AbstractStorageDecl>(Derived);
4030+
return DerivedStorage->getAccessor(Accessor->getAccessorKind());
4031+
}
4032+
4033+
return nullptr;
40224034
}
4023-
return false;
4035+
4036+
return cast_or_null<AbstractFunctionDecl>(::findOverridingDecl(this, Method));
40244037
}
40254038

40264039
AbstractFunctionDecl *
40274040
ClassDecl::findImplementingMethod(const AbstractFunctionDecl *Method) const {
4041+
// FIXME: This is extremely inefficient. The SILOptimizer should build a
4042+
// reverse lookup table to answer these types of queries.
40284043
const ClassDecl *C = this;
40294044
while (C) {
4030-
auto Members = C->getMembers();
4031-
for (auto M : Members) {
4032-
auto *CurMethod = dyn_cast<AbstractFunctionDecl>(M);
4033-
if (!CurMethod)
4034-
continue;
4035-
if (Method == CurMethod)
4036-
return CurMethod;
4037-
if (CurMethod->isOverridingDecl(Method)) {
4038-
// This class implements a method
4039-
return CurMethod;
4040-
}
4041-
}
4045+
if (C == Method->getDeclContext())
4046+
return const_cast<AbstractFunctionDecl *>(Method);
4047+
4048+
if (auto *Derived = C->findOverridingDecl(Method))
4049+
return Derived;
4050+
40424051
// Check the superclass
40434052
C = C->getSuperclassDecl();
40444053
}

lib/AST/DeclContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,7 @@ void IterableDeclContext::addMember(Decl *member, Decl *Hint) {
740740
}
741741

742742
void IterableDeclContext::addMemberSilently(Decl *member, Decl *hint) const {
743+
assert(!isa<AccessorDecl>(member) && "Accessors should not be added here");
743744
assert(!member->NextDecl && "Already added to a container");
744745

745746
// If there is a hint decl that specifies where to add this, just

lib/AST/Module.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,7 +1672,21 @@ bool FileUnit::walk(ASTWalker &walker) {
16721672

16731673
if (D->walk(walker))
16741674
return true;
1675+
1676+
if (walker.shouldWalkAccessorsTheOldWay()) {
1677+
// Pretend that accessors share a parent with the storage.
1678+
//
1679+
// FIXME: Update existing ASTWalkers to deal with accessors appearing as
1680+
// children of the storage instead.
1681+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
1682+
for (auto AD : ASD->getAllAccessors()) {
1683+
if (AD->walk(walker))
1684+
return true;
1685+
}
1686+
}
1687+
}
16751688
}
1689+
16761690
return false;
16771691
}
16781692

@@ -1686,6 +1700,19 @@ bool SourceFile::walk(ASTWalker &walker) {
16861700

16871701
if (D->walk(walker))
16881702
return true;
1703+
1704+
if (walker.shouldWalkAccessorsTheOldWay()) {
1705+
// Pretend that accessors share a parent with the storage.
1706+
//
1707+
// FIXME: Update existing ASTWalkers to deal with accessors appearing as
1708+
// children of the storage instead.
1709+
if (auto *ASD = dyn_cast<AbstractStorageDecl>(D)) {
1710+
for (auto AD : ASD->getAllAccessors()) {
1711+
if (AD->walk(walker))
1712+
return true;
1713+
}
1714+
}
1715+
}
16891716
}
16901717
return false;
16911718
}

lib/AST/Stmt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ BraceStmt::BraceStmt(SourceLoc lbloc, ArrayRef<ASTNode> elts,
141141
Bits.BraceStmt.NumElements = elts.size();
142142
std::uninitialized_copy(elts.begin(), elts.end(),
143143
getTrailingObjects<ASTNode>());
144+
145+
#ifndef NDEBUG
146+
for (auto elt : elts)
147+
if (auto *decl = elt.dyn_cast<Decl *>())
148+
assert(!isa<AccessorDecl>(decl) && "accessors should not be added here");
149+
#endif
144150
}
145151

146152
BraceStmt *BraceStmt::create(ASTContext &ctx, SourceLoc lbloc,

0 commit comments

Comments
 (0)