Skip to content

Commit 76fb4cf

Browse files
authored
Merge pull request #2660 from bnbarham/typed-throws-misparse
Fix up a mismatch between effect specifier lookahead and parsing
2 parents 6d47f0a + 5887f40 commit 76fb4cf

File tree

3 files changed

+31
-40
lines changed

3 files changed

+31
-40
lines changed

Sources/SwiftParser/Expressions.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2428,10 +2428,15 @@ extension Parser.Lookahead {
24282428
// Consume 'async', 'throws', and 'rethrows', but in any order.
24292429
mutating func consumeEffectsSpecifiers() {
24302430
var loopProgress = LoopProgressCondition()
2431-
while let (_, handle) = self.at(anyIn: EffectSpecifier.self),
2431+
while let (spec, handle) = self.at(anyIn: EffectSpecifier.self),
24322432
self.hasProgressed(&loopProgress)
24332433
{
24342434
self.eat(handle)
2435+
2436+
if spec.isThrowsSpecifier, self.consume(if: .leftParen) != nil {
2437+
_ = self.canParseSimpleOrCompositionType()
2438+
self.consume(if: .rightParen)
2439+
}
24352440
}
24362441
}
24372442

Sources/SwiftParser/Types.swift

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extension Parser {
3737
mutating func parseTypeScalar(misplacedSpecifiers: [RawTokenSyntax] = []) -> RawTypeSyntax {
3838
let specifiersAndAttributes = self.parseTypeAttributeList(misplacedSpecifiers: misplacedSpecifiers)
3939
var base = RawTypeSyntax(self.parseSimpleOrCompositionType())
40-
if self.withLookahead({ $0.atFunctionTypeArrow() }) {
40+
if self.withLookahead({ $0.canParseFunctionTypeArrow() }) {
4141
var effectSpecifiers = self.parseTypeEffectSpecifiers()
4242
let returnClause = self.parseFunctionReturnClause(
4343
effectSpecifiers: &effectSpecifiers,
@@ -656,21 +656,9 @@ extension Parser.Lookahead {
656656
return false
657657
}
658658

659-
if self.atFunctionTypeArrow() {
660-
// Handle type-function if we have an '->' with optional
661-
// 'async' and/or 'throws'.
662-
var loopProgress = LoopProgressCondition()
663-
while let (_, handle) = self.at(anyIn: EffectSpecifier.self), self.hasProgressed(&loopProgress) {
664-
self.eat(handle)
665-
}
666-
667-
guard self.consume(if: .arrow) != nil else {
668-
return false
669-
}
670-
659+
if self.canParseFunctionTypeArrow() {
671660
return self.canParseType()
672661
}
673-
674662
return true
675663
}
676664

@@ -819,33 +807,12 @@ extension Parser.Lookahead {
819807
return self.consume(if: .rightParen) != nil
820808
}
821809

822-
mutating func atFunctionTypeArrow() -> Bool {
823-
if self.at(.arrow) {
810+
mutating func canParseFunctionTypeArrow() -> Bool {
811+
if self.consume(if: .arrow) != nil {
824812
return true
825813
}
826-
827-
if let effect = self.at(anyIn: EffectSpecifier.self) {
828-
if self.peek().rawTokenKind == .arrow {
829-
return true
830-
}
831-
832-
if effect.spec.isThrowsSpecifier && self.peek().rawTokenKind == .leftParen {
833-
var lookahead = self.lookahead()
834-
lookahead.consumeAnyToken()
835-
lookahead.skipSingle()
836-
return lookahead.atFunctionTypeArrow()
837-
}
838-
839-
if peek(isAtAnyIn: EffectSpecifier.self) != nil {
840-
var lookahead = self.lookahead()
841-
lookahead.consumeAnyToken()
842-
return lookahead.atFunctionTypeArrow()
843-
}
844-
845-
return false
846-
}
847-
848-
return false
814+
self.consumeEffectsSpecifiers()
815+
return self.consume(if: .arrow) != nil
849816
}
850817

851818
mutating func canParseTypeIdentifier(allowKeyword: Bool = false) -> Bool {

Tests/SwiftParserTest/ExpressionTests.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,6 +2972,9 @@ final class StatementExpressionTests: ParserTestCase {
29722972
assertParse(
29732973
"[() throws(MyError) -> Void]()"
29742974
)
2975+
assertParse(
2976+
"[() throws(any Error) -> Void]()"
2977+
)
29752978
assertParse(
29762979
"X<() throws(MyError) -> Int>()"
29772980
)
@@ -2980,6 +2983,22 @@ final class StatementExpressionTests: ParserTestCase {
29802983
)
29812984
}
29822985
2986+
func testTypedThrowsClosureParam() {
2987+
assertParse(
2988+
"""
2989+
try foo { (a, b) throws(S) in 1 }
2990+
"""
2991+
)
2992+
}
2993+
2994+
func testTypedThrowsShorthandClosureParams() {
2995+
assertParse(
2996+
"""
2997+
try foo { a, b throws(S) in 1 }
2998+
"""
2999+
)
3000+
}
3001+
29833002
func testArrayExprWithNoCommas() {
29843003
assertParse("[() ()]")
29853004

0 commit comments

Comments
 (0)