Repository: swiftlang/swift-syntax (swift)

Issue:
Parser crashes on invalid type signature in closure
The following test case crashes the new parser:

```swift
{ a: (a $
```

```
0  swift-frontend                0x0000000109d88934 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend                0x0000000109d87084 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend                0x0000000109d88f7c SignalHandler(int, __siginfo*, void*) + 296
3  libsystem_platform.dylib      0x0000000194454704 _sigtramp + 56
4  lib_CompilerSwiftParser.dylib 0x0000000116131de0 $s20_CompilerSwiftParser0C0V9LookaheadV21canParseTupleBodyTypeSbyF + 948
5  lib_CompilerSwiftParser.dylib 0x0000000116131de0 $s20_CompilerSwiftParser0C0V9LookaheadV21canParseTupleBodyTypeSbyF + 948
6  lib_CompilerSwiftParser.dylib 0x0000000116130f80 $s20_CompilerSwiftParser0C0V9LookaheadV18canParseSimpleTypeSbyF + 228
7  lib_CompilerSwiftParser.dylib 0x0000000116123fb4 $s20_CompilerSwiftParser0C0V9LookaheadV31canParseSimpleOrCompositionTypeSbyF + 244
8  lib_CompilerSwiftParser.dylib 0x000000011612fe5c $s20_CompilerSwiftParser0C0V9LookaheadV18canParseTypeScalarSbyF + 36
9  lib_CompilerSwiftParser.dylib 0x00000001160b96a0 $s20_CompilerSwiftParser0C0V9LookaheadV24canParseClosureSignatureSbyF + 2428
10 lib_CompilerSwiftParser.dylib 0x00000001160b7e34 $s20_CompilerSwiftParser0C0V30parseClosureSignatureIfPresent01_aB6Syntax03RawefI0VSgyF + 232
11 lib_CompilerSwiftParser.dylib 0x00000001160b0418 $s20_CompilerSwiftParser0C0V22parsePrimaryExpression7pattern6flavor01_aB6Syntax07RawExprI0VAC14PatternContextO_AC0K6FlavorOtF + 1700
12 lib_CompilerSwiftParser.dylib 0x00000001160ad554 $s20_CompilerSwiftParser0C0V20parseUnaryExpression6flavor7pattern01_aB6Syntax07RawExprI0VAC0K6FlavorO_AC14PatternContextOtF + 592
13 lib_CompilerSwiftParser.dylib 0x00000001160aa834 $s20_CompilerSwiftParser0C0V30parseSequenceExpressionElement6flavor7pattern01_aB6Syntax07RawExprJ0VAC0L6FlavorO_AC14PatternContextOtF + 1500
14 lib_CompilerSwiftParser.dylib 0x00000001160a96e8 $s20_CompilerSwiftParser0C0V23parseSequenceExpression6flavor7pattern01_aB6Syntax07RawExprI0VAC0K6FlavorO_AC14PatternContextOtF + 72
15 lib_CompilerSwiftParser.dylib 0x0000000116105a18 $s20_CompilerSwiftParser0C0V9parseItem33_008C1B0E0A90478841CED0DF9A7053A1LL12isAtTopLevel13allowInitDecl01_aB6Syntax012RawCodeBlockeU0V0E0OSb_SbtF + 1240
16 lib_CompilerSwiftParser.dylib 0x00000001161050a4 $s20_CompilerSwiftParser0C0V18parseCodeBlockItem12isAtTopLevel13allowInitDecl01_aB6Syntax03RawefgO0VSgSb_SbtF + 492
17 lib_CompilerSwiftParser.dylib 0x0000000116103524 $s20_CompilerSwiftParser0C0V22parseCodeBlockItemList12isAtTopLevel13allowInitDecl5until01_aB6Syntax03RawefghQ0VSb_S2bACzXEtF05$s20_ab9Syntax017efgh9C0V01_aB6c35E5parse4fromAcD0H0Vz_tFZAA03RawdefgU19VAHzXEfU_SbAHzXEfU_Tf1nncn_nTm + 84
18 lib_CompilerSwiftParser.dylib 0x000000011613991c $s20_CompilerSwiftSyntax010SourceFileC0V01_aB6ParserE5parse4fromAcD0F0Vz_tFZ + 68
19 swift-frontend                0x0000000105b8556c $s11swiftASTGen15parseSourceFile6buffer10moduleName8filename14declContextPtr4kindSVSo16BridgedStringRefV_A2ISvSgSo0n9GenerateddE4KindVtF + 268
```

Pull request:
There was a mismatch between the call to `eat` and `at`. Switch the pair to a `consume(if:)` to avoid the issue.

Fixes swiftlang/swift-syntax#3103

Patch:
diff --git a/Sources/SwiftParser/Types.swift b/Sources/SwiftParser/Types.swift
index 68a6428ef49..67ad666c5df 100644
--- a/Sources/SwiftParser/Types.swift
+++ b/Sources/SwiftParser/Types.swift
@@ -944,13 +944,13 @@ extension Parser.Lookahead {
       // by a type annotation.
       if self.startsParameterName(isClosure: false, allowMisplacedSpecifierRecovery: false) {
         self.consumeAnyToken()
+        // If we have a secondary argument label, consume it.
         if self.atArgumentLabel() {
           self.consumeAnyToken()
-          guard self.at(.colon) else {
-            return false
-          }
         }
-        self.eat(.colon)
+        guard self.consume(if: .colon) != nil else {
+          return false
+        }
 
         // Parse a type.
         guard self.canParseType() else {


Test patch:
diff --git a/Tests/SwiftParserTest/ExpressionTests.swift b/Tests/SwiftParserTest/ExpressionTests.swift
index 3eb7d83add2..40e31d34fc7 100644
--- a/Tests/SwiftParserTest/ExpressionTests.swift
+++ b/Tests/SwiftParserTest/ExpressionTests.swift
@@ -2145,6 +2145,26 @@ final class ExpressionTests: ParserTestCase {
       """
     )
   }
+
+  func testSecondaryArgumentLabelDollarIdentifierInClosure() {
+    assertParse(
+      """
+      ℹ️{ a1️⃣: (a $
+      """,
+      diagnostics: [
+        DiagnosticSpec(
+          message: "expected '}' to end closure",
+          notes: [NoteSpec(message: "to match this opening '{'")],
+          fixIts: ["insert '}'"]
+        ),
+        DiagnosticSpec(message: "extraneous code ': (a $' at top level"),
+      ],
+      fixedSource: """
+        { a
+        }: (a $
+        """
+    )
+  }
 }
 
 final class MemberExprTests: ParserTestCase {