@@ -963,7 +963,8 @@ struct ResultBuilderTarget {
963
963
// / Handles the rewrite of the body of a closure to which a result builder
964
964
// / has been applied.
965
965
class BuilderClosureRewriter
966
- : public StmtVisitor<BuilderClosureRewriter, Stmt *, ResultBuilderTarget> {
966
+ : public StmtVisitor<BuilderClosureRewriter, NullablePtr<Stmt>,
967
+ ResultBuilderTarget> {
967
968
ASTContext &ctx;
968
969
const Solution &solution;
969
970
DeclContext *dc;
@@ -1124,8 +1125,9 @@ class BuilderClosureRewriter
1124
1125
solution (solution), dc(dc), builderTransform(builderTransform),
1125
1126
rewriteTarget(rewriteTarget) { }
1126
1127
1127
- Stmt *visitBraceStmt (BraceStmt *braceStmt, ResultBuilderTarget target,
1128
- Optional<ResultBuilderTarget> innerTarget = None) {
1128
+ NullablePtr<Stmt>
1129
+ visitBraceStmt (BraceStmt *braceStmt, ResultBuilderTarget target,
1130
+ Optional<ResultBuilderTarget> innerTarget = None) {
1129
1131
std::vector<ASTNode> newElements;
1130
1132
1131
1133
// If there is an "inner" target corresponding to this brace, declare
@@ -1165,7 +1167,7 @@ class BuilderClosureRewriter
1165
1167
// "throw" statements produce no value. Transform them directly.
1166
1168
if (auto throwStmt = dyn_cast<ThrowStmt>(stmt)) {
1167
1169
if (auto newStmt = visitThrowStmt (throwStmt)) {
1168
- newElements.push_back (stmt );
1170
+ newElements.push_back (newStmt. get () );
1169
1171
}
1170
1172
continue ;
1171
1173
}
@@ -1176,7 +1178,7 @@ class BuilderClosureRewriter
1176
1178
1177
1179
declareTemporaryVariable (captured.first , newElements);
1178
1180
1179
- Stmt * finalStmt = visit (
1181
+ auto finalStmt = visit (
1180
1182
stmt,
1181
1183
ResultBuilderTarget{ResultBuilderTarget::TemporaryVar,
1182
1184
std::move (captured)});
@@ -1186,7 +1188,7 @@ class BuilderClosureRewriter
1186
1188
if (!finalStmt)
1187
1189
return nullptr ;
1188
1190
1189
- newElements.push_back (finalStmt);
1191
+ newElements.push_back (finalStmt. get () );
1190
1192
continue ;
1191
1193
}
1192
1194
@@ -1236,7 +1238,7 @@ class BuilderClosureRewriter
1236
1238
braceStmt->getRBraceLoc ());
1237
1239
}
1238
1240
1239
- Stmt * visitIfStmt (IfStmt *ifStmt, ResultBuilderTarget target) {
1241
+ NullablePtr< Stmt> visitIfStmt (IfStmt *ifStmt, ResultBuilderTarget target) {
1240
1242
// Rewrite the condition.
1241
1243
if (auto condition = rewriteTarget (
1242
1244
SolutionApplicationTarget (ifStmt->getCond (), dc)))
@@ -1252,7 +1254,10 @@ class BuilderClosureRewriter
1252
1254
temporaryVar, {target.captured .second [0 ]}),
1253
1255
ResultBuilderTarget::forAssign (
1254
1256
capturedThen.first , {capturedThen.second .front ()}));
1255
- ifStmt->setThenStmt (newThen);
1257
+ if (!newThen)
1258
+ return nullptr ;
1259
+
1260
+ ifStmt->setThenStmt (newThen.get ());
1256
1261
1257
1262
// Look for a #available condition. If there is one, we need to check
1258
1263
// that the resulting type of the "then" doesn't refer to any types that
@@ -1315,23 +1320,28 @@ class BuilderClosureRewriter
1315
1320
dyn_cast_or_null<BraceStmt>(ifStmt->getElseStmt ())) {
1316
1321
// Translate the "else" branch when it's a stmt-brace.
1317
1322
auto capturedElse = takeCapturedStmt (elseBraceStmt);
1318
- Stmt * newElse = visitBraceStmt (
1323
+ auto newElse = visitBraceStmt (
1319
1324
elseBraceStmt,
1320
1325
ResultBuilderTarget::forAssign (
1321
1326
temporaryVar, {target.captured .second [1 ]}),
1322
1327
ResultBuilderTarget::forAssign (
1323
1328
capturedElse.first , {capturedElse.second .front ()}));
1324
- ifStmt->setElseStmt (newElse);
1329
+ if (!newElse)
1330
+ return nullptr ;
1331
+
1332
+ ifStmt->setElseStmt (newElse.get ());
1325
1333
} else if (auto elseIfStmt = cast_or_null<IfStmt>(ifStmt->getElseStmt ())){
1326
1334
// Translate the "else" branch when it's an else-if.
1327
1335
auto capturedElse = takeCapturedStmt (elseIfStmt);
1328
1336
std::vector<ASTNode> newElseElements;
1329
1337
declareTemporaryVariable (capturedElse.first , newElseElements);
1330
- newElseElements.push_back (
1331
- visitIfStmt (
1332
- elseIfStmt,
1333
- ResultBuilderTarget::forAssign (
1334
- capturedElse.first , capturedElse.second )));
1338
+ auto newElseElt =
1339
+ visitIfStmt (elseIfStmt, ResultBuilderTarget::forAssign (
1340
+ capturedElse.first , capturedElse.second ));
1341
+ if (!newElseElt)
1342
+ return nullptr ;
1343
+
1344
+ newElseElements.push_back (newElseElt.get ());
1335
1345
newElseElements.push_back (
1336
1346
initializeTarget (
1337
1347
ResultBuilderTarget::forAssign (
@@ -1355,23 +1365,25 @@ class BuilderClosureRewriter
1355
1365
return ifStmt;
1356
1366
}
1357
1367
1358
- Stmt * visitDoStmt (DoStmt *doStmt, ResultBuilderTarget target) {
1368
+ NullablePtr< Stmt> visitDoStmt (DoStmt *doStmt, ResultBuilderTarget target) {
1359
1369
// Each statement turns into a (potential) temporary variable
1360
1370
// binding followed by the statement itself.
1361
1371
auto body = cast<BraceStmt>(doStmt->getBody ());
1362
1372
auto captured = takeCapturedStmt (body);
1363
1373
1364
- auto newInnerBody = cast<BraceStmt>(
1365
- visitBraceStmt (
1366
- body,
1367
- target,
1368
- ResultBuilderTarget::forAssign (
1369
- captured.first , {captured.second .front ()})));
1370
- doStmt->setBody (newInnerBody);
1374
+ auto newInnerBody =
1375
+ visitBraceStmt (body, target,
1376
+ ResultBuilderTarget::forAssign (
1377
+ captured.first , {captured.second .front ()}));
1378
+ if (!newInnerBody)
1379
+ return nullptr ;
1380
+
1381
+ doStmt->setBody (cast<BraceStmt>(newInnerBody.get ()));
1371
1382
return doStmt;
1372
1383
}
1373
1384
1374
- Stmt *visitSwitchStmt (SwitchStmt *switchStmt, ResultBuilderTarget target) {
1385
+ NullablePtr<Stmt> visitSwitchStmt (SwitchStmt *switchStmt,
1386
+ ResultBuilderTarget target) {
1375
1387
// Translate the subject expression.
1376
1388
ConstraintSystem &cs = solution.getConstraintSystem ();
1377
1389
auto subjectTarget =
@@ -1416,7 +1428,8 @@ class BuilderClosureRewriter
1416
1428
return switchStmt;
1417
1429
}
1418
1430
1419
- Stmt *visitCaseStmt (CaseStmt *caseStmt, ResultBuilderTarget target) {
1431
+ NullablePtr<Stmt> visitCaseStmt (CaseStmt *caseStmt,
1432
+ ResultBuilderTarget target) {
1420
1433
// Translate the patterns and guard expressions for each case label item.
1421
1434
for (auto &caseLabelItem : caseStmt->getMutableCaseLabelItems ()) {
1422
1435
SolutionApplicationTarget caseLabelTarget (&caseLabelItem, dc);
@@ -1427,19 +1440,19 @@ class BuilderClosureRewriter
1427
1440
// Transform the body of the case.
1428
1441
auto body = cast<BraceStmt>(caseStmt->getBody ());
1429
1442
auto captured = takeCapturedStmt (body);
1430
- auto newInnerBody = cast<BraceStmt>(
1431
- visitBraceStmt (
1432
- body,
1433
- target,
1434
- ResultBuilderTarget::forAssign (
1435
- captured.first , {captured.second .front ()})));
1436
- caseStmt->setBody (newInnerBody);
1443
+ auto newInnerBody =
1444
+ visitBraceStmt (body, target,
1445
+ ResultBuilderTarget::forAssign (
1446
+ captured.first , {captured.second .front ()}));
1447
+ if (!newInnerBody)
1448
+ return nullptr ;
1437
1449
1450
+ caseStmt->setBody (cast<BraceStmt>(newInnerBody.get ()));
1438
1451
return caseStmt;
1439
1452
}
1440
1453
1441
- Stmt * visitForEachStmt (
1442
- ForEachStmt *forEachStmt, ResultBuilderTarget target) {
1454
+ NullablePtr< Stmt> visitForEachStmt (ForEachStmt *forEachStmt,
1455
+ ResultBuilderTarget target) {
1443
1456
// Translate the for-each loop header.
1444
1457
ConstraintSystem &cs = solution.getConstraintSystem ();
1445
1458
auto forEachTarget =
@@ -1469,13 +1482,14 @@ class BuilderClosureRewriter
1469
1482
// will append the result of executing the loop body to the array.
1470
1483
auto body = forEachStmt->getBody ();
1471
1484
auto capturedBody = takeCapturedStmt (body);
1472
- auto newBody = cast<BraceStmt>(
1473
- visitBraceStmt (
1474
- body,
1475
- ResultBuilderTarget::forExpression (arrayAppendCall),
1476
- ResultBuilderTarget::forAssign (
1477
- capturedBody.first , {capturedBody.second .front ()})));
1478
- forEachStmt->setBody (newBody);
1485
+ auto newBody = visitBraceStmt (
1486
+ body, ResultBuilderTarget::forExpression (arrayAppendCall),
1487
+ ResultBuilderTarget::forAssign (capturedBody.first ,
1488
+ {capturedBody.second .front ()}));
1489
+ if (!newBody)
1490
+ return nullptr ;
1491
+
1492
+ forEachStmt->setBody (cast<BraceStmt>(newBody.get ()));
1479
1493
outerBodySteps.push_back (forEachStmt);
1480
1494
1481
1495
// Step 3. Perform the buildArray() call to turn the array of results
@@ -1487,11 +1501,11 @@ class BuilderClosureRewriter
1487
1501
1488
1502
// Form a brace statement to put together the three main steps for the
1489
1503
// for-each loop translation outlined above.
1490
- return BraceStmt::create (
1491
- ctx, forEachStmt-> getStartLoc (), outerBodySteps, newBody->getEndLoc ());
1504
+ return BraceStmt::create (ctx, forEachStmt-> getStartLoc (), outerBodySteps,
1505
+ newBody. get () ->getEndLoc ());
1492
1506
}
1493
1507
1494
- Stmt * visitThrowStmt (ThrowStmt *throwStmt) {
1508
+ NullablePtr< Stmt> visitThrowStmt (ThrowStmt *throwStmt) {
1495
1509
// Rewrite the error.
1496
1510
auto target = *solution.getConstraintSystem ()
1497
1511
.getSolutionApplicationTarget (throwStmt);
@@ -1503,12 +1517,14 @@ class BuilderClosureRewriter
1503
1517
return throwStmt;
1504
1518
}
1505
1519
1506
- Stmt *visitThrowStmt (ThrowStmt *throwStmt, ResultBuilderTarget target) {
1520
+ NullablePtr<Stmt> visitThrowStmt (ThrowStmt *throwStmt,
1521
+ ResultBuilderTarget target) {
1507
1522
llvm_unreachable (" Throw statements produce no value" );
1508
1523
}
1509
1524
1510
1525
#define UNHANDLED_RESULT_BUILDER_STMT (STMT ) \
1511
- Stmt *visit##STMT##Stmt(STMT##Stmt *stmt, ResultBuilderTarget target) { \
1526
+ NullablePtr<Stmt> \
1527
+ visit##STMT##Stmt(STMT##Stmt *stmt, ResultBuilderTarget target) { \
1512
1528
llvm_unreachable (" Function builders do not allow statement of kind " \
1513
1529
#STMT); \
1514
1530
}
@@ -1540,12 +1556,12 @@ BraceStmt *swift::applyResultBuilderTransform(
1540
1556
rewriteTarget) {
1541
1557
BuilderClosureRewriter rewriter (solution, dc, applied, rewriteTarget);
1542
1558
auto captured = rewriter.takeCapturedStmt (body);
1543
- return cast_or_null<BraceStmt> (
1544
- rewriter. visitBraceStmt (
1545
- body,
1546
- ResultBuilderTarget::forReturn (applied. returnExpr ),
1547
- ResultBuilderTarget::forAssign (
1548
- captured. first , captured. second ) ));
1559
+ auto result = rewriter. visitBraceStmt (
1560
+ body, ResultBuilderTarget::forReturn (applied. returnExpr ),
1561
+ ResultBuilderTarget::forAssign (captured. first , captured. second ));
1562
+ if (!result)
1563
+ return nullptr ;
1564
+ return cast<BraceStmt>(result. get ( ));
1549
1565
}
1550
1566
1551
1567
Optional<BraceStmt *> TypeChecker::applyResultBuilderBodyTransform (
0 commit comments