Skip to content

Commit 2c9def8

Browse files
authored
Merge pull request #26925 from DougGregor/parse-members-request
[Parser] Introduce a request for parsing type and extension members.
2 parents f1f75ca + d8f7c9e commit 2c9def8

24 files changed

+278
-45
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ class ASTContext final {
826826
/// of the given decl context.
827827
///
828828
/// \param IDC The context whose member decls should be lazily parsed.
829-
void parseMembers(IterableDeclContext *IDC);
829+
std::vector<Decl *> parseMembers(IterableDeclContext *IDC);
830830

831831
/// Get the lazy function data for the given generic context.
832832
///

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ SWIFT_TYPEID(AncestryFlags)
3333
SWIFT_TYPEID_NAMED(GenericSignature *, GenericSignature)
3434
SWIFT_TYPEID_NAMED(GenericTypeParamType *, GenericTypeParamType)
3535
SWIFT_TYPEID(Requirement)
36+
SWIFT_TYPEID_NAMED(IterableDeclContext *, IterableDeclContext)

include/swift/AST/ASTTypeIDs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,26 @@
1717
#ifndef SWIFT_AST_ASTTYPEIDS_H
1818
#define SWIFT_AST_ASTTYPEIDS_H
1919

20+
#include "swift/Basic/LLVM.h"
2021
#include "swift/Basic/TypeID.h"
2122
namespace swift {
2223

2324
class CustomAttr;
25+
class Decl;
2426
class GenericSignature;
2527
class GenericTypeParamType;
28+
class IterableDeclContext;
2629
class NominalTypeDecl;
30+
class OperatorDecl;
2731
struct PropertyWrapperBackingPropertyInfo;
2832
struct PropertyWrapperTypeInfo;
2933
enum class CtorInitializerKind;
3034
struct PropertyWrapperMutability;
35+
class ProtocolDecl;
3136
class Requirement;
37+
enum class ResilienceExpansion : unsigned;
3238
class Type;
39+
class ValueDecl;
3340
class VarDecl;
3441
class TypeAliasDecl;
3542
class Type;

include/swift/AST/Decl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7248,6 +7248,17 @@ void simple_display(llvm::raw_ostream &out, const Decl *decl);
72487248
/// Display ValueDecl subclasses.
72497249
void simple_display(llvm::raw_ostream &out, const ValueDecl *decl);
72507250

7251+
/// Display ExtensionDecls.
7252+
inline void simple_display(llvm::raw_ostream &out, const ExtensionDecl *decl) {
7253+
simple_display(out, static_cast<const Decl *>(decl));
7254+
}
7255+
7256+
/// Display NominalTypeDecls.
7257+
inline void simple_display(llvm::raw_ostream &out,
7258+
const NominalTypeDecl *decl) {
7259+
simple_display(out, static_cast<const Decl *>(decl));
7260+
}
7261+
72517262
/// Extract the source location from the given declaration.
72527263
SourceLoc extractNearestSourceLoc(const Decl *decl);
72537264

@@ -7261,6 +7272,11 @@ inline SourceLoc extractNearestSourceLoc(const GenericTypeDecl *type) {
72617272
return extractNearestSourceLoc(static_cast<const Decl *>(type));
72627273
}
72637274

7275+
/// Extract the source location from the given declaration.
7276+
inline SourceLoc extractNearestSourceLoc(const NominalTypeDecl *type) {
7277+
return extractNearestSourceLoc(static_cast<const Decl *>(type));
7278+
}
7279+
72647280
/// Extract the source location from the given declaration.
72657281
inline SourceLoc extractNearestSourceLoc(const AbstractFunctionDecl *func) {
72667282
return extractNearestSourceLoc(static_cast<const Decl *>(func));

include/swift/AST/DeclContext.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -699,8 +699,8 @@ class IterableDeclContext {
699699
/// time, but I think it's a better trade to just keep a count here.
700700
unsigned MemberCount : 29;
701701

702-
/// Whether parsing the members of this context has been delayed.
703-
unsigned HasUnparsedMembers : 1;
702+
/// Whether we have already added the parsed members into the context.
703+
unsigned AddedParsedMembers : 1;
704704

705705
/// Whether delayed parsing detected a possible operator definition
706706
/// while skipping the body of this context.
@@ -722,8 +722,8 @@ class IterableDeclContext {
722722
IterableDeclContext(IterableDeclContextKind kind)
723723
: LastDeclAndKind(nullptr, kind) {
724724
MemberCount = 0;
725+
AddedParsedMembers = 0;
725726
HasOperatorDeclarations = 0;
726-
HasUnparsedMembers = 0;
727727
HasNestedClassDeclarations = 0;
728728
}
729729

@@ -732,13 +732,7 @@ class IterableDeclContext {
732732
return LastDeclAndKind.getInt();
733733
}
734734

735-
bool hasUnparsedMembers() const {
736-
return HasUnparsedMembers;
737-
}
738-
739-
void setHasUnparsedMembers() {
740-
HasUnparsedMembers = 1;
741-
}
735+
bool hasUnparsedMembers() const;
742736

743737
bool maybeHasOperatorDeclarations() const {
744738
return HasOperatorDeclarations;
@@ -839,9 +833,14 @@ void simple_display(llvm::raw_ostream &out, const ParamT *dc) {
839833
out << "(null)";
840834
}
841835

836+
void simple_display(llvm::raw_ostream &out, const IterableDeclContext *idc);
837+
842838
/// Extract the source location from the given declaration context.
843839
SourceLoc extractNearestSourceLoc(const DeclContext *dc);
844840

841+
/// Extract the source location from the given declaration context.
842+
SourceLoc extractNearestSourceLoc(const IterableDeclContext *idc);
843+
845844
} // end namespace swift
846845

847846
namespace llvm {

include/swift/AST/LazyResolver.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,8 @@ class LazyMemberParser {
9090
public:
9191
virtual ~LazyMemberParser() = default;
9292

93-
/// Populates a given decl context \p IDC with all of its members.
94-
///
95-
/// The implementation should add the members to IDC.
96-
virtual void parseMembers(IterableDeclContext *IDC) = 0;
93+
/// Retrieves the parsed members for the given decl context \p IDC.
94+
virtual std::vector<Decl *> parseMembers(IterableDeclContext *IDC) = 0;
9795

9896
/// Return whether the iterable decl context needs parsing.
9997
virtual bool hasUnparsedMembers(const IterableDeclContext *IDC) = 0;

include/swift/AST/ParseRequests.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===--- ParseRequests.h - Parsing Requests ---------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines parsing requests.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#ifndef SWIFT_PARSE_REQUESTS_H
17+
#define SWIFT_PARSE_REQUESTS_H
18+
19+
#include "swift/AST/ASTTypeIDs.h"
20+
#include "swift/AST/SimpleRequest.h"
21+
22+
namespace swift {
23+
24+
/// Report that a request of the given kind is being evaluated, so it
25+
/// can be recorded by the stats reporter.
26+
template<typename Request>
27+
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
28+
const Request &request);
29+
30+
/// Parse the members of a nominal type declaration or extension.
31+
class ParseMembersRequest :
32+
public SimpleRequest<ParseMembersRequest,
33+
ArrayRef<Decl *>(IterableDeclContext *),
34+
CacheKind::Cached>
35+
{
36+
public:
37+
using SimpleRequest::SimpleRequest;
38+
39+
private:
40+
friend SimpleRequest;
41+
42+
// Evaluation.
43+
ArrayRef<Decl *> evaluate(Evaluator &evaluator,
44+
IterableDeclContext *idc) const;
45+
46+
public:
47+
// Caching
48+
bool isCached() const { return true; }
49+
};
50+
51+
/// The zone number for the parser.
52+
#define SWIFT_TYPEID_ZONE Parse
53+
#define SWIFT_TYPEID_HEADER "swift/AST/ParseTypeIDZone.def"
54+
#include "swift/Basic/DefineTypeIDZone.h"
55+
#undef SWIFT_TYPEID_ZONE
56+
#undef SWIFT_TYPEID_HEADER
57+
58+
// Set up reporting of evaluated requests.
59+
#define SWIFT_REQUEST(Zone, RequestType) \
60+
template<> \
61+
inline void reportEvaluatedRequest(UnifiedStatsReporter &stats, \
62+
const RequestType &request) { \
63+
++stats.getFrontendCounters().RequestType; \
64+
}
65+
#include "swift/AST/ParseTypeIDZone.def"
66+
#undef SWIFT_REQUEST
67+
68+
} // end namespace swift
69+
70+
#endif // SWIFT_PARSE_REQUESTS_H

include/swift/AST/ParseTypeIDZone.def

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===--- ParseTypeIDZone.def ------------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This definition file describes the requests in the parser's zone.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
SWIFT_REQUEST(Parse, ParseMembersRequest)

include/swift/Basic/Statistics.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ FRONTEND_STATISTIC(Parse, NumFunctionsParsed)
195195
/// Number of full braced decl list parsed.
196196
FRONTEND_STATISTIC(Parse, NumIterableDeclContextParsed)
197197

198+
#define SWIFT_REQUEST(ZONE, NAME) FRONTEND_STATISTIC(Parse, NAME)
199+
#include "swift/AST/ParseTypeIDZone.def"
200+
#undef SWIFT_REQUEST
201+
198202
/// Number of conformances that were deserialized by this frontend job.
199203
FRONTEND_STATISTIC(Sema, NumConformancesDeserialized)
200204

include/swift/Basic/TypeID.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum class Zone : uint8_t {
3535
IDE = 137,
3636
IDETypeChecking = 97,
3737
NameLookup = 9,
38+
Parse = 8,
3839
TypeChecker = 10,
3940
// N.B. This is not a formal zone and exists solely to support the unit tests.
4041
ArithmeticEvaluator = 255,

include/swift/Parse/Parser.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ class Parser {
971971

972972
void parseDeclDelayed();
973973

974-
void parseDeclListDelayed(IterableDeclContext *IDC);
974+
std::vector<Decl *> parseDeclListDelayed(IterableDeclContext *IDC);
975975

976976
bool parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
977977
SourceLoc PosBeforeLB,
@@ -1080,9 +1080,10 @@ class Parser {
10801080
ParserStatus parseDeclItem(bool &PreviousHadSemi,
10811081
Parser::ParseDeclOptions Options,
10821082
llvm::function_ref<void(Decl*)> handler);
1083-
bool parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
1084-
Diag<> ErrorDiag, ParseDeclOptions Options,
1085-
IterableDeclContext *IDC);
1083+
std::vector<Decl *> parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
1084+
Diag<> ErrorDiag, ParseDeclOptions Options,
1085+
IterableDeclContext *IDC,
1086+
bool &hadError);
10861087
ParserResult<ExtensionDecl> parseDeclExtension(ParseDeclOptions Flags,
10871088
DeclAttributes &Attributes);
10881089
ParserResult<EnumDecl> parseDeclEnum(ParseDeclOptions Flags,

include/swift/Parse/PersistentParserState.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class PersistentParserState: public LazyMemberParser {
153153
void delayTopLevel(TopLevelCodeDecl *TLCD, SourceRange BodyRange,
154154
SourceLoc PreviousLoc);
155155

156-
void parseMembers(IterableDeclContext *IDC) override;
156+
std::vector<Decl *> parseMembers(IterableDeclContext *IDC) override;
157157

158158
bool hasDelayedDecl() {
159159
return CodeCompletionDelayedDeclState.get() != nullptr;

include/swift/Subsystems.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,13 @@ namespace swift {
389389
/// The ASTContext will automatically call these upon construction.
390390
void registerNameLookupRequestFunctions(Evaluator &evaluator);
391391

392+
/// Register Parse-level request functions with the evaluator.
393+
///
394+
/// Clients that form an ASTContext and will perform any parsing queries
395+
/// using Parse-level logic should call these functions after forming the
396+
/// ASTContext.
397+
void registerParseRequestFunctions(Evaluator &evaluator);
398+
392399
/// Register Sema-level request functions with the evaluator.
393400
///
394401
/// Clients that form an ASTContext and will perform any semantic queries

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,12 +2015,14 @@ LazyContextData *ASTContext::getOrCreateLazyContextData(
20152015
return entry;
20162016
}
20172017

2018-
void ASTContext::parseMembers(IterableDeclContext *IDC) {
2018+
std::vector<Decl *> ASTContext::parseMembers(IterableDeclContext *IDC) {
20192019
assert(IDC->hasUnparsedMembers());
20202020
for (auto *p: getImpl().lazyParsers) {
20212021
if (p->hasUnparsedMembers(IDC))
2022-
p->parseMembers(IDC);
2022+
return p->parseMembers(IDC);
20232023
}
2024+
2025+
return { };
20242026
}
20252027

20262028
LazyIterableDeclContextData *ASTContext::getOrCreateLazyIterableContextData(

lib/AST/DeclContext.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/Initializer.h"
2020
#include "swift/AST/LazyResolver.h"
2121
#include "swift/AST/Module.h"
22+
#include "swift/AST/ParseRequests.h"
2223
#include "swift/AST/Types.h"
2324
#include "swift/AST/TypeCheckRequests.h"
2425
#include "swift/Basic/SourceManager.h"
@@ -804,15 +805,39 @@ void IterableDeclContext::setMemberLoader(LazyMemberLoader *loader,
804805
++s->getFrontendCounters().NumUnloadedLazyIterableDeclContexts;
805806
}
806807
}
808+
bool IterableDeclContext::hasUnparsedMembers() const {
809+
if (AddedParsedMembers)
810+
return false;
811+
812+
if (!getDecl()->getDeclContext()->getParentSourceFile()) {
813+
// There will never be any parsed members to add, so set the flag to say
814+
// we are done so we can short-circuit next time.
815+
const_cast<IterableDeclContext *>(this)->AddedParsedMembers = 1;
816+
return false;
817+
}
818+
819+
return true;
820+
}
807821

808822
void IterableDeclContext::loadAllMembers() const {
809823
ASTContext &ctx = getASTContext();
810824

811-
// Lazily parse members.
812-
if (HasUnparsedMembers) {
813-
auto *IDC = const_cast<IterableDeclContext *>(this);
814-
ctx.parseMembers(IDC);
815-
IDC->HasUnparsedMembers = 0;
825+
// For contexts within a source file, get the list of parsed members.
826+
if (getDecl()->getDeclContext()->getParentSourceFile()) {
827+
// Retrieve the parsed members. Even if we've already added the parsed
828+
// members to this context, this call is important for recording the
829+
// dependency edge.
830+
auto mutableThis = const_cast<IterableDeclContext *>(this);
831+
auto members = evaluateOrDefault(
832+
ctx.evaluator, ParseMembersRequest{mutableThis}, ArrayRef<Decl*>());
833+
834+
// If we haven't already done so, add these members to this context.
835+
if (!AddedParsedMembers) {
836+
mutableThis->AddedParsedMembers = 1;
837+
for (auto member : members) {
838+
mutableThis->addMember(member);
839+
}
840+
}
816841
}
817842

818843
if (!hasLazyMembers())
@@ -1072,3 +1097,12 @@ static void verify_DeclContext_is_start_of_node() {
10721097
#include "swift/AST/ExprNodes.def"
10731098
}
10741099
#endif
1100+
1101+
void swift::simple_display(llvm::raw_ostream &out,
1102+
const IterableDeclContext *idc) {
1103+
simple_display(out, idc->getDecl());
1104+
}
1105+
1106+
SourceLoc swift::extractNearestSourceLoc(const IterableDeclContext *idc) {
1107+
return extractNearestSourceLoc(idc->getDecl());
1108+
}

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ TinyPtrVector<ValueDecl *> NominalTypeDecl::lookupDirect(
12251225
// We still have to parse any unparsed extensions.
12261226
if (!ignoreNewExtensions) {
12271227
for (auto *e : getExtensions()) {
1228-
if (e->hasUnparsedMembers())
1228+
if (e->getParentSourceFile() != nullptr)
12291229
e->loadAllMembers();
12301230
}
12311231
}

lib/Frontend/Frontend.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ bool CompilerInstance::setUpASTContextIfNeeded() {
186186
Context.reset(ASTContext::get(Invocation.getLangOptions(),
187187
Invocation.getSearchPathOptions(), SourceMgr,
188188
Diagnostics));
189+
registerParseRequestFunctions(Context->evaluator);
189190
registerTypeCheckerRequestFunctions(Context->evaluator);
190191

191192
// Migrator, indexing and typo correction need some IDE requests.

lib/Parse/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_swift_host_library(swiftParse STATIC
1818
ParseIfConfig.cpp
1919
ParsePattern.cpp
2020
Parser.cpp
21+
ParseRequests.cpp
2122
ParseStmt.cpp
2223
ParseType.cpp
2324
PersistentParserState.cpp

0 commit comments

Comments
 (0)