Skip to content

Commit ae4fbb6

Browse files
committed
[AST] Generalize and rename ClassDecl::getEmittedMembers()
Generalize `ClassDecl::getEmittedMembers()` to operate on an `IterableDeclContext`, so that it can be for other nominal types, extensions, etc. Rename to `getSemanticMembers()` to indicate that these are all of the members that are semantically part of that context. Clean up the implementation slightly so it only forces type checking for the conformances within that particular context (using `getLocalConformances()`) and doesn't need to list out each of the protocols it cares about.
1 parent ab2152b commit ae4fbb6

File tree

12 files changed

+51
-59
lines changed

12 files changed

+51
-59
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,11 @@ class IterableDeclContext {
783783
/// Retrieve the set of members in this context.
784784
DeclRange getMembers() const;
785785

786+
/// Get all the members that are semantically within this context,
787+
/// including any implicitly-synthesized members.
788+
/// The resulting list of members will be stable across translation units.
789+
ArrayRef<Decl *> getSemanticMembers() const;
790+
786791
/// Retrieve the set of members in this context without loading any from the
787792
/// associated lazy loader; this should only be used as part of implementing
788793
/// abstractions on top of member loading, such as a name lookup table.

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ class SynthesizeAccessorRequest :
10821082

10831083
class EmittedMembersRequest :
10841084
public SimpleRequest<EmittedMembersRequest,
1085-
ArrayRef<Decl *>(ClassDecl *),
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, EmittedMembersRequest,
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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,14 @@ DeclRange IterableDeclContext::getMembers() const {
793793
return getCurrentMembersWithoutLoading();
794794
}
795795

796+
ArrayRef<Decl *> IterableDeclContext::getSemanticMembers() const {
797+
ASTContext &ctx = getASTContext();
798+
return evaluateOrDefault(
799+
ctx.evaluator,
800+
EmittedMembersRequest{const_cast<IterableDeclContext *>(this)},
801+
ArrayRef<Decl *>());
802+
}
803+
796804
/// Add a member to this context.
797805
void IterableDeclContext::addMember(Decl *member, Decl *Hint) {
798806
// Add the member to the list of declarations without notification.

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: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,59 +2507,51 @@ struct SortedFuncList {
25072507

25082508
ArrayRef<Decl *>
25092509
EmittedMembersRequest::evaluate(Evaluator &evaluator,
2510-
ClassDecl *CD) const {
2511-
auto &Context = CD->getASTContext();
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.

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2017,7 +2017,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
20172017

20182018
TypeChecker::checkDeclAttributes(CD);
20192019

2020-
for (Decl *Member : CD->getEmittedMembers())
2020+
for (Decl *Member : CD->getSemanticMembers())
20212021
visit(Member);
20222022

20232023
TypeChecker::checkPatternBindingCaptures(CD);

0 commit comments

Comments
 (0)