Skip to content

Commit bfbd812

Browse files
committed
[Parser] Distinguish between backtracking scopes that can be cancelled or not
For backtracking scopes that are never cancelled, we can completely disable the SyntaxParsingContext, avoiding the creation of deferred nodes which will never get recorded.
1 parent 0d913e9 commit bfbd812

File tree

7 files changed

+39
-21
lines changed

7 files changed

+39
-21
lines changed

include/swift/Parse/Parser.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,11 @@ class Parser {
463463
/// RAII object that, when it is destructed, restores the parser and lexer to
464464
/// their positions at the time the object was constructed. Will not jump
465465
/// forward in the token stream.
466-
class BacktrackingScope {
466+
/// Actual uses of the backtracking scope should choose either \c
467+
/// BacktrackingScope, which will always backtrack or \c
468+
/// CancellableBacktrackingScope which can be cancelled.
469+
class BacktrackingScopeImpl {
470+
protected:
467471
Parser &P;
468472
ParserPosition PP;
469473
DiagnosticTransaction DT;
@@ -501,16 +505,32 @@ class Parser {
501505
}
502506
} TempReceiver;
503507

504-
public:
505-
BacktrackingScope(Parser &P)
508+
BacktrackingScopeImpl(Parser &P)
506509
: P(P), PP(P.getParserPosition()), DT(P.Diags),
507510
TempReceiver(P.TokReceiver) {
508511
SynContext.emplace(P.SyntaxContext);
509-
SynContext->setBackTracking();
510512
}
511513

512-
~BacktrackingScope();
514+
public:
515+
~BacktrackingScopeImpl();
513516
bool willBacktrack() const { return Backtrack; }
517+
};
518+
519+
/// A backtracking scope that will always backtrack when destructed.
520+
class BacktrackingScope final : public BacktrackingScopeImpl {
521+
public:
522+
BacktrackingScope(Parser &P) : BacktrackingScopeImpl(P) {
523+
SynContext->disable();
524+
}
525+
};
526+
527+
/// A backtracking scope whose backtracking can be disabled by calling
528+
/// \c cancelBacktrack.
529+
class CancellableBacktrackingScope final : public BacktrackingScopeImpl {
530+
public:
531+
CancellableBacktrackingScope(Parser &P) : BacktrackingScopeImpl(P) {
532+
SynContext->setBackTracking();
533+
}
514534

515535
void cancelBacktrack();
516536
};

include/swift/SyntaxParse/SyntaxTreeCreator.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ class SyntaxTreeCreator final : public SyntaxParseActions {
4848
/// tree.
4949
SyntaxParsingCache *SyntaxCache;
5050

51-
llvm::BumpPtrAllocator ScratchAlloc;
52-
5351
public:
5452
SyntaxTreeCreator(SourceManager &SM, unsigned bufferID,
5553
SyntaxParsingCache *syntaxCache,

lib/Parse/ParseDecl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,7 @@ static Optional<AccessorKind> isAccessorLabel(const Token &token) {
11201120
/// or to `nullptr` if not. A missing base type is not considered an error.
11211121
static bool parseBaseTypeForQualifiedDeclName(Parser &P, TypeRepr *&baseType) {
11221122
baseType = nullptr;
1123-
Parser::BacktrackingScope backtrack(P);
1123+
Parser::CancellableBacktrackingScope backtrack(P);
11241124

11251125
// If base type cannot be parsed, return false (no error).
11261126
if (!P.canParseBaseTypeForQualifiedDeclName())
@@ -3028,7 +3028,7 @@ bool Parser::canParseTypeAttribute() {
30283028
/// \returns true on error, false on success
30293029
static bool parseDifferentiableTypeAttributeArgument(
30303030
Parser &P, TypeAttributes &Attributes, bool emitDiagnostics) {
3031-
Parser::BacktrackingScope backtrack(P);
3031+
Parser::CancellableBacktrackingScope backtrack(P);
30323032

30333033
// Match '( <identifier> )', and store the identifier token to `argument`.
30343034
if (!P.consumeIf(tok::l_paren))
@@ -3226,7 +3226,7 @@ bool Parser::parseTypeAttribute(TypeAttributes &Attributes, SourceLoc AtLoc,
32263226
SyntaxParsingContext TokListContext(SyntaxContext, SyntaxKind::TokenList);
32273227

32283228
if (Tok.is(tok::l_paren) && getEndOfPreviousLoc() == Tok.getLoc()) {
3229-
BacktrackingScope backtrack(*this);
3229+
CancellableBacktrackingScope backtrack(*this);
32303230
skipSingle();
32313231
// If we found '->', or 'throws' after paren, it's likely a parameter
32323232
// of function type.
@@ -5046,7 +5046,7 @@ bool Parser::canDelayMemberDeclParsing(bool &HasOperatorDeclarations,
50465046

50475047
// Skip until the matching right curly bracket; if we find a pound directive,
50485048
// we can't lazily parse.
5049-
BacktrackingScope BackTrack(*this);
5049+
CancellableBacktrackingScope BackTrack(*this);
50505050
bool HasPoundDirective;
50515051
bool HasNestedTypeDeclarations;
50525052
skipUntilMatchingRBrace(*this,
@@ -5975,7 +5975,7 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags,
59755975
};
59765976

59775977
// Prepare backtracking for implicit getter.
5978-
Optional<BacktrackingScope> backtrack;
5978+
Optional<CancellableBacktrackingScope> backtrack;
59795979
backtrack.emplace(*this);
59805980

59815981
bool Invalid = false;
@@ -7114,7 +7114,7 @@ Parser::parseDeclEnumCase(ParseDeclOptions Flags,
71147114
// For recovery, see if the user typed something resembling a switch
71157115
// "case" label.
71167116
{
7117-
BacktrackingScope backtrack(*this);
7117+
CancellableBacktrackingScope backtrack(*this);
71187118
llvm::SaveAndRestore<decltype(InVarOrLetPattern)>
71197119
T(InVarOrLetPattern, Parser::IVOLP_InMatchingPattern);
71207120
parseMatchingPattern(/*isExprBasic*/false);

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2083,7 +2083,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
20832083

20842084
// Try to parse a compound name.
20852085
SyntaxParsingContext ArgsCtxt(P.SyntaxContext, SyntaxKind::DeclNameArguments);
2086-
Parser::BacktrackingScope backtrack(P);
2086+
Parser::CancellableBacktrackingScope backtrack(P);
20872087

20882088
lparenLoc = P.consumeToken(tok::l_paren);
20892089
while (P.Tok.isNot(tok::r_paren)) {

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,8 @@ ParserResult<Pattern> Parser::parseTypedPattern() {
968968
// Disable this tentative parse when in code-completion mode, otherwise
969969
// code-completion may enter the delayed-decl state twice.
970970
if (Tok.isFollowingLParen() && !L->isCodeCompletion()) {
971-
BacktrackingScope backtrack(*this);
972-
971+
CancellableBacktrackingScope backtrack(*this);
972+
973973
// Create a local context if needed so we can parse trailing closures.
974974
LocalContext dummyContext;
975975
Optional<ContextChange> contextChange;

lib/Parse/ParseType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ ParserResult<TypeRepr> Parser::parseTypeTupleBody() {
999999
// 'inout' here can be a obsoleted use of the marker in an argument list,
10001000
// consume it in backtracking context so we can determine it's really a
10011001
// deprecated use of it.
1002-
llvm::Optional<BacktrackingScope> Backtracking;
1002+
llvm::Optional<CancellableBacktrackingScope> Backtracking;
10031003
SourceLoc ObsoletedInOutLoc;
10041004
if (Tok.is(tok::kw_inout)) {
10051005
Backtracking.emplace(*this);

lib/Parse/Parser.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,14 @@ void Parser::performCodeCompletionSecondPassImpl(
214214
State->restoreCodeCompletionDelayedDeclState(info);
215215
}
216216

217-
swift::Parser::BacktrackingScope::~BacktrackingScope() {
217+
swift::Parser::BacktrackingScopeImpl::~BacktrackingScopeImpl() {
218218
if (Backtrack) {
219219
P.backtrackToPosition(PP);
220220
DT.abort();
221221
}
222222
}
223223

224-
void swift::Parser::BacktrackingScope::cancelBacktrack() {
224+
void swift::Parser::CancellableBacktrackingScope::cancelBacktrack() {
225225
if (!Backtrack)
226226
return;
227227

@@ -783,8 +783,8 @@ void Parser::skipListUntilDeclRBrace(SourceLoc startLoc, tok T1, tok T2) {
783783
if (possibleDeclStartsLine && !hasDelimiter) {
784784
break;
785785
}
786-
787-
Parser::BacktrackingScope backtrack(*this);
786+
787+
Parser::CancellableBacktrackingScope backtrack(*this);
788788
// Consume the let or var
789789
consumeToken();
790790

0 commit comments

Comments
 (0)