Skip to content

Revert "Add a request to lazily parse function bodies." #26978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5594,8 +5594,6 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
SourceRange BodyRange;
};

friend class ParseAbstractFunctionBodyRequest;

CaptureInfo Captures;

/// Location of the 'throws' token.
Expand Down
22 changes: 0 additions & 22 deletions include/swift/AST/ParseRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,6 @@ class ParseMembersRequest :
bool isCached() const { return true; }
};

/// Parse the body of a function, initializer, or deinitializer.
class ParseAbstractFunctionBodyRequest :
public SimpleRequest<ParseAbstractFunctionBodyRequest,
BraceStmt *(AbstractFunctionDecl *),
CacheKind::SeparatelyCached>
{
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
BraceStmt *evaluate(Evaluator &evaluator, AbstractFunctionDecl *afd) const;

public:
// Caching
bool isCached() const { return true; }
Optional<BraceStmt *> getCachedResult() const;
void cacheResult(BraceStmt *value) const;
};

/// The zone number for the parser.
#define SWIFT_TYPEID_ZONE Parse
#define SWIFT_TYPEID_HEADER "swift/AST/ParseTypeIDZone.def"
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/ParseTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@
//===----------------------------------------------------------------------===//

SWIFT_REQUEST(Parse, ParseMembersRequest)
SWIFT_REQUEST(Parse, ParseAbstractFunctionBodyRequest)
2 changes: 1 addition & 1 deletion include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ class Parser {
DeclAttributes &Attributes,
bool HasFuncKeyword = true);
void parseAbstractFunctionBody(AbstractFunctionDecl *AFD);
BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
bool parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
DeclAttributes &Attributes);

Expand Down
8 changes: 8 additions & 0 deletions include/swift/Parse/PersistentParserState.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ class PersistentParserState {
PersistentParserState(ASTContext &ctx) : PersistentParserState() { }
~PersistentParserState();

void delayFunctionBodyParsing(AbstractFunctionDecl *AFD,
SourceRange BodyRange,
SourceLoc PreviousLoc);
std::unique_ptr<FunctionBodyState>
takeFunctionBodyState(AbstractFunctionDecl *AFD);

bool hasFunctionBodyState(AbstractFunctionDecl *AFD);

void delayDecl(DelayedDeclKind Kind, unsigned Flags,
DeclContext *ParentContext,
SourceRange BodyRange, SourceLoc PreviousLoc);
Expand Down
6 changes: 1 addition & 5 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,9 @@ PrintOptions PrintOptions::printParseableInterfaceFile(bool preferTypeRepr) {

result.FunctionBody = [](const ValueDecl *decl, ASTPrinter &printer) {
auto AFD = dyn_cast<AbstractFunctionDecl>(decl);
if (!AFD)
return;
if (!AFD || !AFD->hasInlinableBodyText()) return;
if (AFD->getResilienceExpansion() != ResilienceExpansion::Minimal)
return;
if (!AFD->hasInlinableBodyText())
return;

SmallString<128> scratch;
printer << " " << AFD->getInlinableBodyText(scratch);
};
Expand Down
6 changes: 3 additions & 3 deletions lib/AST/ASTScopeCreation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ void AbstractFunctionDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
// Create scope for the body.
// We create body scopes when there is no body for source kit to complete
// erroneous code in bodies. But don't let compiler synthesize one.
if (decl->getBodySourceRange().isValid() && decl->getBody(false)) {
if (decl->getBody(false) && decl->getBodySourceRange().isValid()) {
if (AbstractFunctionBodyScope::isAMethod(decl))
scopeCreator.constructExpandAndInsertUncheckable<MethodBodyScope>(leaf,
decl);
Expand Down Expand Up @@ -1771,10 +1771,10 @@ bool IterableTypeScope::isBodyCurrent() const {
}

void AbstractFunctionBodyScope::beCurrent() {
bodyWhenLastExpanded = decl->getBody(false);
bodyWhenLastExpanded = decl->getBody();
}
bool AbstractFunctionBodyScope::isCurrent() const {
return bodyWhenLastExpanded == decl->getBody(false);
return bodyWhenLastExpanded == decl->getBody();
;
}

Expand Down
92 changes: 28 additions & 64 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include "swift/AST/NameLookup.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ParseRequests.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/PropertyWrappers.h"
#include "swift/AST/ProtocolConformance.h"
Expand Down Expand Up @@ -6308,22 +6307,37 @@ bool AbstractFunctionDecl::argumentNameIsAPIByDefault() const {
}

BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
if ((getBodyKind() == BodyKind::Synthesize ||
getBodyKind() == BodyKind::Unparsed) &&
!canSynthesize)
switch (getBodyKind()) {
case BodyKind::Deserialized:
case BodyKind::MemberwiseInitializer:
case BodyKind::None:
case BodyKind::Skipped:
return nullptr;

ASTContext &ctx = getASTContext();
case BodyKind::Parsed:
case BodyKind::TypeChecked:
return Body;

// Don't allow getBody() to trigger parsing of an unparsed body containing the
// code completion location.
if (getBodyKind() == BodyKind::Unparsed &&
ctx.SourceMgr.rangeContainsCodeCompletionLoc(getBodySourceRange())) {
case BodyKind::Unparsed:
// FIXME: Go parse now!
return nullptr;
}

auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
return evaluateOrDefault(ctx.evaluator, ParseAbstractFunctionBodyRequest{mutableThis}, nullptr);
case BodyKind::Synthesize: {
if (!canSynthesize)
return nullptr;

const_cast<AbstractFunctionDecl *>(this)->setBodyKind(BodyKind::None);
BraceStmt *body;
bool isTypeChecked;

auto mutableThis = const_cast<AbstractFunctionDecl *>(this);
std::tie(body, isTypeChecked) = (Synthesizer.Fn)(
mutableThis, Synthesizer.Context);
mutableThis->setBody(
body, isTypeChecked ? BodyKind::TypeChecked : BodyKind::Parsed);
return body;
}
}
}

SourceRange AbstractFunctionDecl::getBodySourceRange() const {
Expand Down Expand Up @@ -6790,15 +6804,11 @@ bool AbstractFunctionDecl::hasInlinableBodyText() const {
switch (getBodyKind()) {
case BodyKind::Deserialized:
return true;

case BodyKind::Unparsed:
case BodyKind::Parsed:
case BodyKind::TypeChecked:
if (auto body = getBody())
return !body->isImplicit();
return false;

return getBody() && !getBody()->isImplicit();
case BodyKind::None:
case BodyKind::Unparsed:
case BodyKind::Synthesize:
case BodyKind::Skipped:
case BodyKind::MemberwiseInitializer:
Expand Down Expand Up @@ -7666,49 +7676,3 @@ SourceLoc swift::extractNearestSourceLoc(const Decl *decl) {

return extractNearestSourceLoc(decl->getDeclContext());
}

Optional<BraceStmt *>
ParseAbstractFunctionBodyRequest::getCachedResult() const {
using BodyKind = AbstractFunctionDecl::BodyKind;
auto afd = std::get<0>(getStorage());
switch (afd->getBodyKind()) {
case BodyKind::Deserialized:
case BodyKind::MemberwiseInitializer:
case BodyKind::None:
case BodyKind::Skipped:
return nullptr;

case BodyKind::TypeChecked:
case BodyKind::Parsed:
return afd->Body;

case BodyKind::Synthesize:
case BodyKind::Unparsed:
return None;
}
}

void ParseAbstractFunctionBodyRequest::cacheResult(BraceStmt *value) const {
using BodyKind = AbstractFunctionDecl::BodyKind;
auto afd = std::get<0>(getStorage());
switch (afd->getBodyKind()) {
case BodyKind::Deserialized:
case BodyKind::MemberwiseInitializer:
case BodyKind::None:
case BodyKind::Skipped:
// The body is always empty, so don't cache anything.
assert(value == nullptr);
return;

case BodyKind::Parsed:
case BodyKind::TypeChecked:
afd->Body = value;
return;

case BodyKind::Synthesize:
case BodyKind::Unparsed:
llvm_unreachable("evaluate() did not set the body kind");
return;
}

}
6 changes: 2 additions & 4 deletions lib/AST/UnqualifiedLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ void UnqualifiedLookupFactory::lookupNamesIntroducedByFunctionDecl(
const bool isCascadingUse =
AFD->isCascadingContextForLookup(false) &&
(isCascadingUseArg.getValueOr(
Loc.isInvalid() || AFD->getBodySourceRange().isInvalid() ||
Loc.isInvalid() || !AFD->getBody() ||
!SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc)));

if (AFD->getDeclContext()->isTypeContext())
Expand Down Expand Up @@ -814,9 +814,7 @@ void UnqualifiedLookupFactory::lookForLocalVariablesIn(
// FIXME: when we can parse and typecheck the function body partially
// for code completion, AFD->getBody() check can be removed.

if (Loc.isInvalid() || AFD->getBodySourceRange().isInvalid() ||
!SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc) ||
!AFD->getBody()) {
if (Loc.isInvalid() || !AFD->getBody()) {
return;
}

Expand Down
25 changes: 19 additions & 6 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5390,6 +5390,8 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,
if (DelayedParseCB &&
DelayedParseCB->shouldDelayFunctionBodyParsing(*this, AFD, Attrs,
BodyRange)) {
State->delayFunctionBodyParsing(AFD, BodyRange,
BeginParserPosition.PreviousLoc);
AFD->setBodyDelayed(BodyRange);
} else {
AFD->setBodySkipped(BodyRange);
Expand Down Expand Up @@ -5670,12 +5672,15 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
}
}

BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
bool Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
assert(!AFD->getBody() && "function should not have a parsed body");
assert(AFD->getBodyKind() == AbstractFunctionDecl::BodyKind::Unparsed &&
"function body should be delayed");

auto bodyRange = AFD->getBodySourceRange();
auto BeginParserPosition = getParserPosition({bodyRange.Start,bodyRange.End});
auto FunctionParserState = State->takeFunctionBodyState(AFD);
assert(FunctionParserState.get() && "should have a valid state");

auto BeginParserPosition = getParserPosition(FunctionParserState->BodyPos);
auto EndLexerState = L->getStateForEndOfTokenLoc(AFD->getEndLoc());

// ParserPositionRAII needs a primed parser to restore to.
Expand All @@ -5695,12 +5700,20 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
restoreParserPosition(BeginParserPosition);

// Re-enter the lexical scope.
Scope TopLevelScope(this, ScopeKind::TopLevel);
Scope S(this, ScopeKind::FunctionBody);
Scope S(this, FunctionParserState->takeScope());
ParseFunctionBody CC(*this, AFD);
setLocalDiscriminatorToParamList(AFD->getParameters());

return parseBraceItemList(diag::func_decl_without_brace).getPtrOrNull();
ParserResult<BraceStmt> Body =
parseBraceItemList(diag::func_decl_without_brace);
if (Body.isNull()) {
// FIXME: Should do some sort of error recovery here?
return true;
} else {
AFD->setBodyParsed(Body.get());
}

return false;
}

/// Parse a 'enum' declaration, returning true (and doing no token
Expand Down
44 changes: 0 additions & 44 deletions lib/Parse/ParseRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,50 +48,6 @@ ParseMembersRequest::evaluate(Evaluator &evaluator,
llvm::makeArrayRef(parser.parseDeclListDelayed(idc)));
}

BraceStmt *ParseAbstractFunctionBodyRequest::evaluate(
Evaluator &evaluator, AbstractFunctionDecl *afd) const {
using BodyKind = AbstractFunctionDecl::BodyKind;

switch (afd->getBodyKind()) {
case BodyKind::Deserialized:
case BodyKind::MemberwiseInitializer:
case BodyKind::None:
case BodyKind::Skipped:
return nullptr;

case BodyKind::TypeChecked:
case BodyKind::Parsed:
return afd->Body;

case BodyKind::Synthesize: {
BraceStmt *body;
bool isTypeChecked;

std::tie(body, isTypeChecked) = (afd->Synthesizer.Fn)(
afd, afd->Synthesizer.Context);
afd->setBodyKind(isTypeChecked ? BodyKind::TypeChecked : BodyKind::Parsed);
return body;
}

case BodyKind::Unparsed: {
// FIXME: It should be fine to delay body parsing of local functions, so
// the DelayBodyParsing should go away entirely
// FIXME: How do we configure code completion?
SourceFile &sf = *afd->getDeclContext()->getParentSourceFile();
SourceManager &sourceMgr = sf.getASTContext().SourceMgr;
unsigned bufferID = sourceMgr.findBufferContainingLoc(afd->getLoc());
Parser parser(bufferID, sf, nullptr, nullptr, nullptr,
/*DelayBodyParsing=*/false);
parser.SyntaxContext->setDiscard();
auto body = parser.parseAbstractFunctionBodyDelayed(afd);
afd->setBodyKind(BodyKind::Parsed);
return body;
}
}

}


// Define request evaluation functions for each of the type checker requests.
static AbstractRequestFunction *parseRequestFunctions[] = {
#define SWIFT_REQUEST(Zone, Name) \
Expand Down
7 changes: 2 additions & 5 deletions lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,6 @@ class ParseDelayedFunctionBodies : public ASTWalker {

private:
void parseFunctionBody(AbstractFunctionDecl *AFD) {
// FIXME: This duplicates the evaluation of
// ParseAbstractFunctionBodyRequest, but installs a code completion
// factory.
assert(AFD->getBodyKind() == FuncDecl::BodyKind::Unparsed);

SourceFile &SF = *AFD->getDeclContext()->getParentSourceFile();
Expand All @@ -155,8 +152,8 @@ class ParseDelayedFunctionBodies : public ASTWalker {
CodeCompletionFactory->createCodeCompletionCallbacks(TheParser));
TheParser.setCodeCompletionCallbacks(CodeCompletion.get());
}
auto body = TheParser.parseAbstractFunctionBodyDelayed(AFD);
AFD->setBodyParsed(body);
if (ParserState.hasFunctionBodyState(AFD))
TheParser.parseAbstractFunctionBodyDelayed(AFD);

if (CodeCompletion)
CodeCompletion->doneParsing();
Expand Down
Loading