Skip to content

Commit 8555d1b

Browse files
authored
Merge pull request #27286 from nathawes/r55280477-tuple-type-syntax-round-trip
[parser] Fix invalid tuple type round-tripping issue
2 parents e315b6f + e89efa8 commit 8555d1b

File tree

5 files changed

+30
-13
lines changed

5 files changed

+30
-13
lines changed

include/swift/Parse/Parser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ class Parser {
876876
///
877877
/// If the input is malformed, this emits the specified error diagnostic.
878878
bool parseToken(tok K, SourceLoc &TokLoc, const Diagnostic &D);
879-
llvm::Optional<ParsedTokenSyntax> parseTokenSyntax(tok K,
879+
llvm::Optional<ParsedTokenSyntax> parseTokenSyntax(tok K, SourceLoc &TokLoc,
880880
const Diagnostic &D);
881881

882882
template<typename ...DiagArgTypes, typename ...ArgTypes>
@@ -896,7 +896,8 @@ class Parser {
896896
SourceLoc OtherLoc);
897897

898898
llvm::Optional<ParsedTokenSyntax>
899-
parseMatchingTokenSyntax(tok K, Diag<> ErrorDiag, SourceLoc OtherLoc);
899+
parseMatchingTokenSyntax(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
900+
SourceLoc OtherLoc);
900901

901902
/// Returns the proper location for a missing right brace, parenthesis, etc.
902903
SourceLoc getLocForMissingMatchingToken() const;

lib/Parse/ParseType.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ Parser::parseLayoutConstraintSyntax() {
109109
if (Tok.is(tok::r_paren))
110110
builder.useRightParen(consumeTokenSyntax(tok::r_paren));
111111
} else {
112-
auto rParen = parseMatchingTokenSyntax(tok::r_paren,
112+
SourceLoc rParenLoc;
113+
auto rParen = parseMatchingTokenSyntax(tok::r_paren, rParenLoc,
113114
diag::expected_rparen_layout_constraint,
114115
lParenLoc);
115116
if (rParen)
@@ -1166,6 +1167,8 @@ Parser::TypeResult Parser::parseTypeTupleBody() {
11661167
});
11671168

11681169
if (!Status.isSuccess()) {
1170+
if (RParen)
1171+
Junk.push_back(std::move(*RParen));
11691172
auto ty = ParsedSyntaxRecorder::makeUnknownType(Junk, *SyntaxContext);
11701173
return makeParsedResult(std::move(ty), Status);
11711174
}
@@ -1253,9 +1256,9 @@ Parser::TypeResult Parser::parseTypeArray(ParsedTypeSyntax Base,
12531256
// Ignore integer literal between '[' and ']'
12541257
ignoreIf(tok::integer_literal);
12551258

1256-
auto RSquareLoc = Tok.getLoc();
1259+
SourceLoc RSquareLoc;
12571260
auto RSquare = parseMatchingTokenSyntax(
1258-
tok::r_square, diag::expected_rbracket_array_type, LSquareLoc);
1261+
tok::r_square, RSquareLoc, diag::expected_rbracket_array_type, LSquareLoc);
12591262

12601263
if (RSquare) {
12611264
// If we parsed something valid, diagnose it with a fixit to rewrite it to
@@ -1301,7 +1304,9 @@ Parser::TypeResult Parser::parseTypeCollection() {
13011304
auto Diag = Colon ? diag::expected_rbracket_dictionary_type
13021305
: diag::expected_rbracket_array_type;
13031306

1304-
auto RSquare = parseMatchingTokenSyntax(tok::r_square, Diag, LSquareLoc);
1307+
SourceLoc RSquareLoc;
1308+
auto RSquare = parseMatchingTokenSyntax(tok::r_square, RSquareLoc, Diag,
1309+
LSquareLoc);
13051310
if (!RSquare)
13061311
Status.setIsParseError();
13071312

lib/Parse/Parser.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,8 +1242,10 @@ bool Parser::parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
12421242
return false;
12431243
}
12441244

1245-
Optional<ParsedTokenSyntax> Parser::parseTokenSyntax(tok K, const Diagnostic &D) {
1245+
Optional<ParsedTokenSyntax> Parser::parseTokenSyntax(tok K, SourceLoc &TokLoc,
1246+
const Diagnostic &D) {
12461247
if (Tok.is(K)) {
1248+
TokLoc = Tok.getLoc();
12471249
return consumeTokenSyntax();
12481250
}
12491251

@@ -1253,7 +1255,7 @@ Optional<ParsedTokenSyntax> Parser::parseTokenSyntax(tok K, const Diagnostic &D)
12531255
}
12541256

12551257
Optional<ParsedTokenSyntax>
1256-
Parser::parseMatchingTokenSyntax(tok K, Diag<> ErrorDiag, SourceLoc OtherLoc) {
1258+
Parser::parseMatchingTokenSyntax(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag, SourceLoc OtherLoc) {
12571259
Diag<> OtherNote;
12581260
switch (K) {
12591261
case tok::r_paren: OtherNote = diag::opening_paren; break;
@@ -1262,9 +1264,11 @@ Parser::parseMatchingTokenSyntax(tok K, Diag<> ErrorDiag, SourceLoc OtherLoc) {
12621264
default: llvm_unreachable("unknown matching token!");
12631265
}
12641266

1265-
auto Token = parseTokenSyntax(K, ErrorDiag);
1266-
if (!Token)
1267+
auto Token = parseTokenSyntax(K, TokLoc, ErrorDiag);
1268+
if (!Token) {
1269+
TokLoc = getLocForMissingMatchingToken();
12671270
diagnose(OtherLoc, OtherNote);
1271+
}
12681272
return Token;
12691273
}
12701274

@@ -1391,9 +1395,14 @@ Parser::parseListSyntax(tok RightK, SourceLoc LeftLoc,
13911395

13921396
if (Status.isError()) {
13931397
// If we've already got errors, don't emit missing RightK diagnostics.
1394-
RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
1398+
if (Tok.is(RightK)) {
1399+
RightLoc = Tok.getLoc();
1400+
Right = consumeTokenSyntax(RightK);
1401+
} else {
1402+
RightLoc = getLocForMissingMatchingToken();
1403+
}
13951404
} else {
1396-
Right = parseMatchingTokenSyntax(RightK, ErrorDiag, LeftLoc);
1405+
Right = parseMatchingTokenSyntax(RightK, RightLoc, ErrorDiag, LeftLoc);
13971406
if (!Right)
13981407
Status.setIsParseError();
13991408
}

test/Syntax/Outputs/round_trip_invalid.swift.withkinds

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ class C <MemberDeclBlock>{<MemberDeclListItem><StructDecl>
1919
struct S <MemberDeclBlock>{<MemberDeclListItem><EnumDecl>
2020
enum E <MemberDeclBlock>{<MemberDeclListItem><ProtocolDecl>
2121
protocol P <MemberDeclBlock>{<MemberDeclListItem><ExtensionDecl>
22-
extension <SimpleTypeIdentifier>P </SimpleTypeIdentifier><MemberDeclBlock>{</MemberDeclBlock></ExtensionDecl></MemberDeclListItem></MemberDeclBlock></ProtocolDecl></MemberDeclListItem></MemberDeclBlock></EnumDecl></MemberDeclListItem></MemberDeclBlock></StructDecl></MemberDeclListItem></MemberDeclBlock></ClassDecl></CodeBlock></FunctionDecl>
22+
extension <SimpleTypeIdentifier>P </SimpleTypeIdentifier><MemberDeclBlock>{<MemberDeclListItem><InitializerDecl><DeclModifier>
23+
public </DeclModifier>init<ParameterClause>(<FunctionParameter>a: (<TupleTypeElement><SimpleTypeIdentifier>Int </SimpleTypeIdentifier></TupleTypeElement>|| String)</FunctionParameter>)</ParameterClause></InitializerDecl></MemberDeclListItem></MemberDeclBlock></ExtensionDecl></MemberDeclListItem></MemberDeclBlock></ProtocolDecl></MemberDeclListItem></MemberDeclBlock></EnumDecl></MemberDeclListItem></MemberDeclBlock></StructDecl></MemberDeclListItem></MemberDeclBlock></ClassDecl></CodeBlock></FunctionDecl>

test/Syntax/round_trip_invalid.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ struct S {
2020
enum E {
2121
protocol P {
2222
extension P {
23+
public init(a: (Int || String))

0 commit comments

Comments
 (0)