Skip to content

Commit 5665985

Browse files
authored
Merge pull request #33747 from DougGregor/generalize-get-emitted-members
[AST] Generalize and rename ClassDecl::getEmittedMembers()
2 parents c3d4560 + ccca4fd commit 5665985

File tree

13 files changed

+88
-71
lines changed

13 files changed

+88
-71
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3886,7 +3886,7 @@ class ClassDecl final : public NominalTypeDecl {
38863886

38873887
friend class SuperclassDeclRequest;
38883888
friend class SuperclassTypeRequest;
3889-
friend class EmittedMembersRequest;
3889+
friend class SemanticMembersRequest;
38903890
friend class HasMissingDesignatedInitializersRequest;
38913891
friend class InheritsSuperclassInitializersRequest;
38923892

@@ -4074,10 +4074,6 @@ class ClassDecl final : public NominalTypeDecl {
40744074
/// Record the presence of an @objc method with the given selector.
40754075
void recordObjCMethod(AbstractFunctionDecl *method, ObjCSelector selector);
40764076

4077-
/// Get all the members of this class, synthesizing any implicit members
4078-
/// that appear in the vtable if needed.
4079-
ArrayRef<Decl *> getEmittedMembers() const;
4080-
40814077
// Implement isa/cast/dyncast/etc.
40824078
static bool classof(const Decl *D) {
40834079
return D->getKind() == DeclKind::Class;

include/swift/AST/DeclContext.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,16 @@ class IterableDeclContext {
783783
/// Retrieve the set of members in this context.
784784
DeclRange getMembers() const;
785785

786+
/// Get the members that were syntactically present in the source code,
787+
/// and will not contain any members that are implicitly synthesized by
788+
/// the implementation.
789+
ArrayRef<Decl *> getParsedMembers() const;
790+
791+
/// Get all the members that are semantically within this context,
792+
/// including any implicitly-synthesized members.
793+
/// The resulting list of members will be stable across translation units.
794+
ArrayRef<Decl *> getSemanticMembers() const;
795+
786796
/// Retrieve the set of members in this context without loading any from the
787797
/// associated lazy loader; this should only be used as part of implementing
788798
/// abstractions on top of member loading, such as a name lookup table.

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,9 +1080,9 @@ class SynthesizeAccessorRequest :
10801080
void cacheResult(AccessorDecl *value) const;
10811081
};
10821082

1083-
class EmittedMembersRequest :
1084-
public SimpleRequest<EmittedMembersRequest,
1085-
ArrayRef<Decl *>(ClassDecl *),
1083+
class SemanticMembersRequest :
1084+
public SimpleRequest<SemanticMembersRequest,
1085+
ArrayRef<Decl *>(IterableDeclContext *),
10861086
RequestFlags::Cached> {
10871087
public:
10881088
using SimpleRequest::SimpleRequest;
@@ -1092,7 +1092,7 @@ class EmittedMembersRequest :
10921092

10931093
// Evaluation.
10941094
ArrayRef<Decl *>
1095-
evaluate(Evaluator &evaluator, ClassDecl *classDecl) const;
1095+
evaluate(Evaluator &evaluator, IterableDeclContext *idc) const;
10961096

10971097
public:
10981098
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ SWIFT_REQUEST(TypeChecker, TypeEraserHasViableInitRequest,
6565
SWIFT_REQUEST(TypeChecker, DynamicallyReplacedDeclRequest,
6666
ValueDecl *(ValueDecl *),
6767
Cached, NoLocationInfo)
68-
SWIFT_REQUEST(TypeChecker, EmittedMembersRequest, ArrayRef<Decl *>(ClassDecl *),
69-
Cached, NoLocationInfo)
68+
SWIFT_REQUEST(TypeChecker, SemanticMembersRequest,
69+
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
7070
SWIFT_REQUEST(TypeChecker, EnumRawValuesRequest,
7171
evaluator::SideEffect (EnumDecl *, TypeResolutionStage),
7272
SeparatelyCached, NoLocationInfo)

include/swift/SIL/SILVTableVisitor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ template <class T> class SILVTableVisitor {
148148
if (!theClass->hasKnownSwiftImplementation())
149149
return;
150150

151-
for (auto member : theClass->getEmittedMembers())
151+
for (auto member : theClass->getSemanticMembers())
152152
maybeAddMember(member);
153153
}
154154
};

lib/AST/Decl.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4181,13 +4181,6 @@ DestructorDecl *ClassDecl::getDestructor() const {
41814181
nullptr);
41824182
}
41834183

4184-
ArrayRef<Decl *> ClassDecl::getEmittedMembers() const {
4185-
ASTContext &ctx = getASTContext();
4186-
return evaluateOrDefault(ctx.evaluator,
4187-
EmittedMembersRequest{const_cast<ClassDecl *>(this)},
4188-
ArrayRef<Decl *>());
4189-
}
4190-
41914184
/// Synthesizer callback for an empty implicit function body.
41924185
static std::pair<BraceStmt *, bool>
41934186
synthesizeEmptyFunctionBody(AbstractFunctionDecl *afd, void *context) {

lib/AST/DeclContext.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,23 @@ DeclRange IterableDeclContext::getMembers() const {
793793
return getCurrentMembersWithoutLoading();
794794
}
795795

796+
ArrayRef<Decl *> IterableDeclContext::getParsedMembers() const {
797+
ASTContext &ctx = getASTContext();
798+
auto mutableThis = const_cast<IterableDeclContext *>(this);
799+
return evaluateOrDefault(
800+
ctx.evaluator, ParseMembersRequest{mutableThis},
801+
FingerprintAndMembers())
802+
.members;
803+
}
804+
805+
ArrayRef<Decl *> IterableDeclContext::getSemanticMembers() const {
806+
ASTContext &ctx = getASTContext();
807+
return evaluateOrDefault(
808+
ctx.evaluator,
809+
SemanticMembersRequest{const_cast<IterableDeclContext *>(this)},
810+
ArrayRef<Decl *>());
811+
}
812+
796813
/// Add a member to this context.
797814
void IterableDeclContext::addMember(Decl *member, Decl *Hint) {
798815
// Add the member to the list of declarations without notification.
@@ -891,10 +908,7 @@ void IterableDeclContext::loadAllMembers() const {
891908
// members to this context, this call is important for recording the
892909
// dependency edge.
893910
auto mutableThis = const_cast<IterableDeclContext *>(this);
894-
auto members =
895-
evaluateOrDefault(ctx.evaluator, ParseMembersRequest{mutableThis},
896-
FingerprintAndMembers())
897-
.members;
911+
auto members = getParsedMembers();
898912

899913
// If we haven't already done so, add these members to this context.
900914
if (!AddedParsedMembers) {

lib/Parse/ParseRequests.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,29 @@ void swift::simple_display(llvm::raw_ostream &out,
4949
FingerprintAndMembers
5050
ParseMembersRequest::evaluate(Evaluator &evaluator,
5151
IterableDeclContext *idc) const {
52-
SourceFile &sf = *idc->getAsGenericContext()->getParentSourceFile();
53-
unsigned bufferID = *sf.getBufferID();
52+
SourceFile *sf = idc->getAsGenericContext()->getParentSourceFile();
53+
ASTContext &ctx = idc->getDecl()->getASTContext();
54+
if (!sf) {
55+
// If there is no parent source file, this is a deserialized or synthesized
56+
// declaration context, in which case `getMembers()` has all of the members.
57+
// Filter out the implicitly-generated ones.
58+
SmallVector<Decl *, 4> members;
59+
for (auto decl : idc->getMembers()) {
60+
if (!decl->isImplicit()) {
61+
members.push_back(decl);
62+
}
63+
}
64+
65+
return FingerprintAndMembers{None, ctx.AllocateCopy(members)};
66+
}
67+
68+
unsigned bufferID = *sf->getBufferID();
5469

5570
// Lexer diaganostics have been emitted during skipping, so we disable lexer's
5671
// diagnostic engine here.
57-
Parser parser(bufferID, sf, /*No Lexer Diags*/nullptr, nullptr, nullptr);
72+
Parser parser(bufferID, *sf, /*No Lexer Diags*/nullptr, nullptr, nullptr);
5873
// Disable libSyntax creation in the delayed parsing.
5974
parser.SyntaxContext->disable();
60-
ASTContext &ctx = idc->getDecl()->getASTContext();
6175
auto declsAndHash = parser.parseDeclListDelayed(idc);
6276
FingerprintAndMembers fingerprintAndMembers = {declsAndHash.second,
6377
declsAndHash.first};

lib/SILGen/SILGenType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
10381038

10391039
// Build a vtable if this is a class.
10401040
if (auto theClass = dyn_cast<ClassDecl>(theType)) {
1041-
for (Decl *member : theClass->getEmittedMembers())
1041+
for (Decl *member : theClass->getSemanticMembers())
10421042
visit(member);
10431043

10441044
SILGenVTable genVTable(SGM, theClass);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,60 +2506,52 @@ struct SortedFuncList {
25062506
} // end namespace
25072507

25082508
ArrayRef<Decl *>
2509-
EmittedMembersRequest::evaluate(Evaluator &evaluator,
2510-
ClassDecl *CD) const {
2511-
auto &Context = CD->getASTContext();
2509+
SemanticMembersRequest::evaluate(Evaluator &evaluator,
2510+
IterableDeclContext *idc) const {
2511+
auto dc = cast<DeclContext>(idc->getDecl());
2512+
auto &Context = dc->getASTContext();
25122513
SmallVector<Decl *, 8> result;
25132514

2514-
if (!CD->getParentSourceFile()) {
2515-
auto members = CD->getMembers();
2515+
if (!dc->getParentSourceFile()) {
2516+
auto members = idc->getMembers();
25162517
result.append(members.begin(), members.end());
25172518
return Context.AllocateCopy(result);
25182519
}
25192520

2520-
// We need to add implicit initializers because they
2521-
// affect vtable layout.
2522-
TypeChecker::addImplicitConstructors(CD);
2521+
auto nominal = dyn_cast<NominalTypeDecl>(idc);
25232522

2524-
auto forceConformance = [&](ProtocolDecl *protocol) {
2525-
auto ref = CD->getParentModule()->lookupConformance(
2526-
CD->getDeclaredInterfaceType(), protocol);
2527-
if (ref.isInvalid()) {
2528-
return;
2529-
}
2523+
if (nominal) {
2524+
// We need to add implicit initializers because they
2525+
// affect vtable layout.
2526+
TypeChecker::addImplicitConstructors(nominal);
2527+
}
25302528

2531-
auto conformance = ref.getConcrete();
2532-
if (conformance->getDeclContext() == CD &&
2533-
conformance->getState() == ProtocolConformanceState::Incomplete) {
2529+
// Force any derivable conformances in this context. This ensures that any
2530+
// synthesized members will approach in the member list.
2531+
for (auto conformance : idc->getLocalConformances()) {
2532+
if (conformance->getState() == ProtocolConformanceState::Incomplete &&
2533+
conformance->getProtocol()->getKnownDerivableProtocolKind())
25342534
TypeChecker::checkConformance(conformance->getRootNormalConformance());
2535-
}
2536-
};
2535+
}
25372536

2538-
// If the class is Encodable, Decodable or Hashable, force those
2539-
// conformances to ensure that the synthesized members appear in the vtable.
2540-
//
2541-
// FIXME: Generalize this to other protocols for which
2542-
// we can derive conformances.
2543-
forceConformance(Context.getProtocol(KnownProtocolKind::Decodable));
2544-
forceConformance(Context.getProtocol(KnownProtocolKind::Encodable));
2545-
forceConformance(Context.getProtocol(KnownProtocolKind::Hashable));
2546-
forceConformance(Context.getProtocol(KnownProtocolKind::Differentiable));
2547-
2548-
// If the class conforms to Encodable or Decodable, even via an extension,
2537+
// If the type conforms to Encodable or Decodable, even via an extension,
25492538
// the CodingKeys enum is synthesized as a member of the type itself.
25502539
// Force it into existence.
2551-
(void) evaluateOrDefault(Context.evaluator,
2552-
ResolveImplicitMemberRequest{CD,
2553-
ImplicitMemberAction::ResolveCodingKeys},
2554-
{});
2540+
if (nominal) {
2541+
(void) evaluateOrDefault(Context.evaluator,
2542+
ResolveImplicitMemberRequest{nominal,
2543+
ImplicitMemberAction::ResolveCodingKeys},
2544+
{});
2545+
}
25552546

2556-
// If the class has a @main attribute, we need to force synthesis of the
2547+
// If the decl has a @main attribute, we need to force synthesis of the
25572548
// $main function.
2558-
(void) evaluateOrDefault(Context.evaluator,
2559-
SynthesizeMainFunctionRequest{CD},
2560-
nullptr);
2549+
(void) evaluateOrDefault(
2550+
Context.evaluator,
2551+
SynthesizeMainFunctionRequest{const_cast<Decl *>(idc->getDecl())},
2552+
nullptr);
25612553

2562-
for (auto *member : CD->getMembers()) {
2554+
for (auto *member : idc->getMembers()) {
25632555
if (auto *var = dyn_cast<VarDecl>(member)) {
25642556
// The projected storage wrapper ($foo) might have dynamically-dispatched
25652557
// accessors, so force them to be synthesized.
@@ -2570,7 +2562,7 @@ EmittedMembersRequest::evaluate(Evaluator &evaluator,
25702562

25712563
SortedFuncList synthesizedMembers;
25722564

2573-
for (auto *member : CD->getMembers()) {
2565+
for (auto *member : idc->getMembers()) {
25742566
if (auto *afd = dyn_cast<AbstractFunctionDecl>(member)) {
25752567
// Add synthesized members to a side table and sort them by their mangled
25762568
// name, since they could have been added to the class in any order.

0 commit comments

Comments
 (0)