Skip to content

Commit c4e265e

Browse files
committed
[Type checker] Add "all members" request.
Introduce an "all members" request to compute all of the members of a given iterable declaration context in stable order. This builds on ABI members so that it will also include, e.g., type aliases synthesized for associated types.
1 parent a8f7f0d commit c4e265e

File tree

6 files changed

+92
-14
lines changed

6 files changed

+92
-14
lines changed

include/swift/AST/DeclContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,12 @@ class IterableDeclContext {
784784
/// The resulting list of members will be stable across translation units.
785785
ArrayRef<Decl *> getABIMembers() const;
786786

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

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,24 @@ class ABIMembersRequest :
12381238
bool isCached() const { return true; }
12391239
};
12401240

1241+
class AllMembersRequest :
1242+
public SimpleRequest<AllMembersRequest,
1243+
ArrayRef<Decl *>(IterableDeclContext *),
1244+
RequestFlags::Cached> {
1245+
public:
1246+
using SimpleRequest::SimpleRequest;
1247+
1248+
private:
1249+
friend SimpleRequest;
1250+
1251+
// Evaluation.
1252+
ArrayRef<Decl *>
1253+
evaluate(Evaluator &evaluator, IterableDeclContext *idc) const;
1254+
1255+
public:
1256+
bool isCached() const { return true; }
1257+
};
1258+
12411259
class IsImplicitlyUnwrappedOptionalRequest :
12421260
public SimpleRequest<IsImplicitlyUnwrappedOptionalRequest,
12431261
bool(ValueDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ SWIFT_REQUEST(TypeChecker, DynamicallyReplacedDeclRequest,
6767
Cached, NoLocationInfo)
6868
SWIFT_REQUEST(TypeChecker, ABIMembersRequest,
6969
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
70+
SWIFT_REQUEST(TypeChecker, AllMembersRequest,
71+
ArrayRef<Decl *>(IterableDeclContext *), Cached, NoLocationInfo)
7072
SWIFT_REQUEST(TypeChecker, SpecializeAttrTargetDeclRequest,
7173
ValueDecl *(const ValueDecl *, SpecializeAttr *),
7274
Cached, NoLocationInfo)

lib/AST/DeclContext.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,14 @@ ArrayRef<Decl *> IterableDeclContext::getABIMembers() const {
766766
ArrayRef<Decl *>());
767767
}
768768

769+
ArrayRef<Decl *> IterableDeclContext::getAllMembers() const {
770+
ASTContext &ctx = getASTContext();
771+
return evaluateOrDefault(
772+
ctx.evaluator,
773+
AllMembersRequest{const_cast<IterableDeclContext *>(this)},
774+
ArrayRef<Decl *>());
775+
}
776+
769777
void IterableDeclContext::addMemberPreservingSourceOrder(Decl *member) {
770778
auto &SM = getASTContext().SourceMgr;
771779

lib/Sema/TypeCheckDecl.cpp

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,14 +2550,23 @@ struct SortedDeclList {
25502550

25512551
} // end namespace
25522552

2553-
ArrayRef<Decl *>
2554-
ABIMembersRequest::evaluate(
2555-
Evaluator &evaluator, IterableDeclContext *idc) const {
2553+
namespace {
2554+
enum class MembersRequestKind {
2555+
ABI,
2556+
All,
2557+
};
2558+
2559+
}
2560+
2561+
/// Evaluate a request for a particular set of members of an iterable
2562+
/// declaration context.
2563+
static ArrayRef<Decl *> evaluateMembersRequest(
2564+
IterableDeclContext *idc, MembersRequestKind kind) {
25562565
auto dc = cast<DeclContext>(idc->getDecl());
2557-
auto &Context = dc->getASTContext();
2566+
auto &ctx = dc->getASTContext();
25582567
SmallVector<Decl *, 8> result;
25592568

2560-
// Esnure that we add any synthesized members.
2569+
// Ensure that we add any synthesized members.
25612570
if (dc->getParentSourceFile()) {
25622571
auto nominal = dyn_cast<NominalTypeDecl>(idc);
25632572

@@ -2567,20 +2576,43 @@ ABIMembersRequest::evaluate(
25672576
TypeChecker::addImplicitConstructors(nominal);
25682577
}
25692578

2570-
// Force any derivable conformances in this context. This ensures that any
2571-
// synthesized members will approach in the member list.
2579+
// Force any conformances that may introduce more members.
25722580
for (auto conformance : idc->getLocalConformances()) {
2573-
if (conformance->getState() == ProtocolConformanceState::Incomplete &&
2574-
conformance->getProtocol()->getKnownDerivableProtocolKind())
2575-
TypeChecker::checkConformance(conformance->getRootNormalConformance());
2581+
auto proto = conformance->getProtocol();
2582+
bool isDerivable =
2583+
conformance->getState() == ProtocolConformanceState::Incomplete &&
2584+
proto->getKnownDerivableProtocolKind();
2585+
2586+
switch (kind) {
2587+
case MembersRequestKind::ABI:
2588+
// Force any derivable conformances in this context.
2589+
if (isDerivable)
2590+
break;
2591+
2592+
continue;
2593+
2594+
case MembersRequestKind::All:
2595+
// Force any derivable conformances.
2596+
if (isDerivable)
2597+
break;
2598+
2599+
// If there are any associated types in the protocol, they might add
2600+
// type aliases here.
2601+
if (!proto->getAssociatedTypeMembers().empty())
2602+
break;
2603+
2604+
continue;
2605+
}
2606+
2607+
TypeChecker::checkConformance(conformance->getRootNormalConformance());
25762608
}
25772609

25782610
// If the type conforms to Encodable or Decodable, even via an extension,
25792611
// the CodingKeys enum is synthesized as a member of the type itself.
25802612
// Force it into existence.
25812613
if (nominal) {
25822614
(void) evaluateOrDefault(
2583-
Context.evaluator,
2615+
ctx.evaluator,
25842616
ResolveImplicitMemberRequest{nominal,
25852617
ImplicitMemberAction::ResolveCodingKeys},
25862618
{});
@@ -2589,7 +2621,7 @@ ABIMembersRequest::evaluate(
25892621
// If the decl has a @main attribute, we need to force synthesis of the
25902622
// $main function.
25912623
(void) evaluateOrDefault(
2592-
Context.evaluator,
2624+
ctx.evaluator,
25932625
SynthesizeMainFunctionRequest{const_cast<Decl *>(idc->getDecl())},
25942626
nullptr);
25952627

@@ -2633,7 +2665,19 @@ ABIMembersRequest::evaluate(
26332665
result.push_back(pair.second);
26342666
}
26352667

2636-
return Context.AllocateCopy(result);
2668+
return ctx.AllocateCopy(result);
2669+
}
2670+
2671+
ArrayRef<Decl *>
2672+
ABIMembersRequest::evaluate(
2673+
Evaluator &evaluator, IterableDeclContext *idc) const {
2674+
return evaluateMembersRequest(idc, MembersRequestKind::ABI);
2675+
}
2676+
2677+
ArrayRef<Decl *>
2678+
AllMembersRequest::evaluate(
2679+
Evaluator &evaluator, IterableDeclContext *idc) const {
2680+
return evaluateMembersRequest(idc, MembersRequestKind::All);
26372681
}
26382682

26392683
bool TypeChecker::isPassThroughTypealias(TypeAliasDecl *typealias,

lib/Sema/TypeCheckDeclPrimary.cpp

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

21302130
TypeChecker::checkDeclAttributes(CD);
21312131

2132-
for (Decl *Member : CD->getABIMembers())
2132+
for (Decl *Member : CD->getAllMembers())
21332133
visit(Member);
21342134

21352135
TypeChecker::checkPatternBindingCaptures(CD);

0 commit comments

Comments
 (0)