From 902e76e4c8c3d0e65b7c1b3b3dde6a3a925853a5 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Mon, 16 Jun 2025 14:58:17 +0200 Subject: [PATCH] Fix a crash if we had a dollar identifier as the second parameter label in a closure not followed by a colon 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 --- Sources/SwiftParser/Types.swift | 8 ++++---- Tests/SwiftParserTest/ExpressionTests.swift | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) 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 { 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 {