Skip to content

Commit 9255371

Browse files
committed
[ASTGen] Handle 'try' at the first element of SequenceExprSyntax
TryExpr must be hosted to wrap the whole sequence expression.
1 parent 996e720 commit 9255371

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

lib/ASTGen/Sources/ASTGen/Exprs.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,18 @@ extension ASTGenVisitor {
10981098
var elements: [BridgedExpr] = []
10991099
elements.reserveCapacity(node.elements.count)
11001100

1101+
// If the left-most sequence expr is a 'try', hoist it up to turn
1102+
// '(try x) + y' into 'try (x + y)'. This is necessary to do in the
1103+
// ASTGen because 'try' nodes are represented in the ASTScope tree
1104+
// to look up catch nodes. The scope tree must be syntactic because
1105+
// it's constructed before sequence folding happens during preCheckExpr.
1106+
// Otherwise, catch node lookup would find the incorrect catch node for
1107+
// 'try x + y' at the source location for 'y'.
1108+
//
1109+
// 'try' has restrictions for where it can appear within a sequence
1110+
// expr. This is still diagnosed in TypeChecker::foldSequence.
1111+
let firstTryExprSyntax = node.elements.first?.as(TryExprSyntax.self)
1112+
11011113
var iter = node.elements.makeIterator()
11021114
while let node = iter.next() {
11031115
switch node.as(ExprSyntaxEnum.self) {
@@ -1124,15 +1136,24 @@ extension ASTGenVisitor {
11241136
case .unresolvedTernaryExpr(let node):
11251137
elements.append(self.generate(unresolvedTernaryExpr: node).asExpr)
11261138
default:
1127-
// Operand.
1128-
elements.append(self.generate(expr: node))
1139+
if let firstTryExprSyntax, node.id == firstTryExprSyntax.id {
1140+
elements.append(self.generate(expr: firstTryExprSyntax.expression))
1141+
} else {
1142+
elements.append(self.generate(expr: node))
1143+
}
11291144
}
11301145
}
11311146

1132-
return BridgedSequenceExpr.createParsed(
1147+
let seqExpr = BridgedSequenceExpr.createParsed(
11331148
self.ctx,
11341149
exprs: elements.lazy.bridgedArray(in: self)
11351150
).asExpr
1151+
1152+
if let firstTryExprSyntax {
1153+
return self.generate(tryExpr: firstTryExprSyntax, overridingSubExpr: seqExpr)
1154+
} else {
1155+
return seqExpr
1156+
}
11361157
}
11371158

11381159
func generate(subscriptCallExpr node: SubscriptCallExprSyntax, postfixIfConfigBaseExpr: BridgedExpr? = nil) -> BridgedSubscriptExpr {
@@ -1164,9 +1185,9 @@ extension ASTGenVisitor {
11641185
)
11651186
}
11661187

1167-
func generate(tryExpr node: TryExprSyntax) -> BridgedExpr {
1188+
func generate(tryExpr node: TryExprSyntax, overridingSubExpr: BridgedExpr? = nil) -> BridgedExpr {
11681189
let tryLoc = self.generateSourceLoc(node.tryKeyword)
1169-
let subExpr = self.generate(expr: node.expression)
1190+
let subExpr = overridingSubExpr ?? self.generate(expr: node.expression)
11701191

11711192
switch node.questionOrExclamationMark {
11721193
case nil:

test/ASTGen/exprs.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ func testUnaryExprs() async throws {
8585
let bar = copy foo
8686
let baz = consume foo
8787
}
88+
func throwsFunc() throws -> Int { 1 }
89+
func testOptionalTry() {
90+
let _ = try! 1 + throwsFunc()
91+
let _ = try? throwsFunc() + throwsFunc()
92+
}
8893

8994
func testRepeatEach<each T>(_ t: repeat each T) -> (repeat each T) {
9095
return (repeat each t)

0 commit comments

Comments
 (0)