@@ -977,7 +977,8 @@ struct ResultBuilderTarget {
977
977
// / Handles the rewrite of the body of a closure to which a result builder
978
978
// / has been applied.
979
979
class BuilderClosureRewriter
980
- : public StmtVisitor<BuilderClosureRewriter, Stmt *, ResultBuilderTarget> {
980
+ : public StmtVisitor<BuilderClosureRewriter, NullablePtr<Stmt>,
981
+ ResultBuilderTarget> {
981
982
ASTContext &ctx;
982
983
const Solution &solution;
983
984
DeclContext *dc;
@@ -1138,8 +1139,9 @@ class BuilderClosureRewriter
1138
1139
solution (solution), dc(dc), builderTransform(builderTransform),
1139
1140
rewriteTarget(rewriteTarget) { }
1140
1141
1141
- Stmt *visitBraceStmt (BraceStmt *braceStmt, ResultBuilderTarget target,
1142
- Optional<ResultBuilderTarget> innerTarget = None) {
1142
+ NullablePtr<Stmt>
1143
+ visitBraceStmt (BraceStmt *braceStmt, ResultBuilderTarget target,
1144
+ Optional<ResultBuilderTarget> innerTarget = None) {
1143
1145
std::vector<ASTNode> newElements;
1144
1146
1145
1147
// If there is an "inner" target corresponding to this brace, declare
@@ -1179,7 +1181,7 @@ class BuilderClosureRewriter
1179
1181
// "throw" statements produce no value. Transform them directly.
1180
1182
if (auto throwStmt = dyn_cast<ThrowStmt>(stmt)) {
1181
1183
if (auto newStmt = visitThrowStmt (throwStmt)) {
1182
- newElements.push_back (stmt );
1184
+ newElements.push_back (newStmt. get () );
1183
1185
}
1184
1186
continue ;
1185
1187
}
@@ -1190,7 +1192,7 @@ class BuilderClosureRewriter
1190
1192
1191
1193
declareTemporaryVariable (captured.first , newElements);
1192
1194
1193
- Stmt * finalStmt = visit (
1195
+ auto finalStmt = visit (
1194
1196
stmt,
1195
1197
ResultBuilderTarget{ResultBuilderTarget::TemporaryVar,
1196
1198
std::move (captured)});
@@ -1200,7 +1202,7 @@ class BuilderClosureRewriter
1200
1202
if (!finalStmt)
1201
1203
return nullptr ;
1202
1204
1203
- newElements.push_back (finalStmt);
1205
+ newElements.push_back (finalStmt. get () );
1204
1206
continue ;
1205
1207
}
1206
1208
@@ -1250,7 +1252,7 @@ class BuilderClosureRewriter
1250
1252
braceStmt->getRBraceLoc ());
1251
1253
}
1252
1254
1253
- Stmt * visitIfStmt (IfStmt *ifStmt, ResultBuilderTarget target) {
1255
+ NullablePtr< Stmt> visitIfStmt (IfStmt *ifStmt, ResultBuilderTarget target) {
1254
1256
// Rewrite the condition.
1255
1257
if (auto condition = rewriteTarget (
1256
1258
SolutionApplicationTarget (ifStmt->getCond (), dc)))
@@ -1266,7 +1268,10 @@ class BuilderClosureRewriter
1266
1268
temporaryVar, {target.captured .second [0 ]}),
1267
1269
ResultBuilderTarget::forAssign (
1268
1270
capturedThen.first , {capturedThen.second .front ()}));
1269
- ifStmt->setThenStmt (newThen);
1271
+ if (!newThen)
1272
+ return nullptr ;
1273
+
1274
+ ifStmt->setThenStmt (newThen.get ());
1270
1275
1271
1276
// Look for a #available condition. If there is one, we need to check
1272
1277
// that the resulting type of the "then" doesn't refer to any types that
@@ -1338,23 +1343,28 @@ class BuilderClosureRewriter
1338
1343
dyn_cast_or_null<BraceStmt>(ifStmt->getElseStmt ())) {
1339
1344
// Translate the "else" branch when it's a stmt-brace.
1340
1345
auto capturedElse = takeCapturedStmt (elseBraceStmt);
1341
- Stmt * newElse = visitBraceStmt (
1346
+ auto newElse = visitBraceStmt (
1342
1347
elseBraceStmt,
1343
1348
ResultBuilderTarget::forAssign (
1344
1349
temporaryVar, {target.captured .second [1 ]}),
1345
1350
ResultBuilderTarget::forAssign (
1346
1351
capturedElse.first , {capturedElse.second .front ()}));
1347
- ifStmt->setElseStmt (newElse);
1352
+ if (!newElse)
1353
+ return nullptr ;
1354
+
1355
+ ifStmt->setElseStmt (newElse.get ());
1348
1356
} else if (auto elseIfStmt = cast_or_null<IfStmt>(ifStmt->getElseStmt ())){
1349
1357
// Translate the "else" branch when it's an else-if.
1350
1358
auto capturedElse = takeCapturedStmt (elseIfStmt);
1351
1359
std::vector<ASTNode> newElseElements;
1352
1360
declareTemporaryVariable (capturedElse.first , newElseElements);
1353
- newElseElements.push_back (
1354
- visitIfStmt (
1355
- elseIfStmt,
1356
- ResultBuilderTarget::forAssign (
1357
- capturedElse.first , capturedElse.second )));
1361
+ auto newElseElt =
1362
+ visitIfStmt (elseIfStmt, ResultBuilderTarget::forAssign (
1363
+ capturedElse.first , capturedElse.second ));
1364
+ if (!newElseElt)
1365
+ return nullptr ;
1366
+
1367
+ newElseElements.push_back (newElseElt.get ());
1358
1368
newElseElements.push_back (
1359
1369
initializeTarget (
1360
1370
ResultBuilderTarget::forAssign (
@@ -1378,23 +1388,25 @@ class BuilderClosureRewriter
1378
1388
return ifStmt;
1379
1389
}
1380
1390
1381
- Stmt * visitDoStmt (DoStmt *doStmt, ResultBuilderTarget target) {
1391
+ NullablePtr< Stmt> visitDoStmt (DoStmt *doStmt, ResultBuilderTarget target) {
1382
1392
// Each statement turns into a (potential) temporary variable
1383
1393
// binding followed by the statement itself.
1384
1394
auto body = cast<BraceStmt>(doStmt->getBody ());
1385
1395
auto captured = takeCapturedStmt (body);
1386
1396
1387
- auto newInnerBody = cast<BraceStmt>(
1388
- visitBraceStmt (
1389
- body,
1390
- target,
1391
- ResultBuilderTarget::forAssign (
1392
- captured.first , {captured.second .front ()})));
1393
- doStmt->setBody (newInnerBody);
1397
+ auto newInnerBody =
1398
+ visitBraceStmt (body, target,
1399
+ ResultBuilderTarget::forAssign (
1400
+ captured.first , {captured.second .front ()}));
1401
+ if (!newInnerBody)
1402
+ return nullptr ;
1403
+
1404
+ doStmt->setBody (cast<BraceStmt>(newInnerBody.get ()));
1394
1405
return doStmt;
1395
1406
}
1396
1407
1397
- Stmt *visitSwitchStmt (SwitchStmt *switchStmt, ResultBuilderTarget target) {
1408
+ NullablePtr<Stmt> visitSwitchStmt (SwitchStmt *switchStmt,
1409
+ ResultBuilderTarget target) {
1398
1410
// Translate the subject expression.
1399
1411
ConstraintSystem &cs = solution.getConstraintSystem ();
1400
1412
auto subjectTarget =
@@ -1439,7 +1451,8 @@ class BuilderClosureRewriter
1439
1451
return switchStmt;
1440
1452
}
1441
1453
1442
- Stmt *visitCaseStmt (CaseStmt *caseStmt, ResultBuilderTarget target) {
1454
+ NullablePtr<Stmt> visitCaseStmt (CaseStmt *caseStmt,
1455
+ ResultBuilderTarget target) {
1443
1456
// Translate the patterns and guard expressions for each case label item.
1444
1457
for (auto &caseLabelItem : caseStmt->getMutableCaseLabelItems ()) {
1445
1458
SolutionApplicationTarget caseLabelTarget (&caseLabelItem, dc);
@@ -1450,19 +1463,19 @@ class BuilderClosureRewriter
1450
1463
// Transform the body of the case.
1451
1464
auto body = cast<BraceStmt>(caseStmt->getBody ());
1452
1465
auto captured = takeCapturedStmt (body);
1453
- auto newInnerBody = cast<BraceStmt>(
1454
- visitBraceStmt (
1455
- body,
1456
- target,
1457
- ResultBuilderTarget::forAssign (
1458
- captured.first , {captured.second .front ()})));
1459
- caseStmt->setBody (newInnerBody);
1466
+ auto newInnerBody =
1467
+ visitBraceStmt (body, target,
1468
+ ResultBuilderTarget::forAssign (
1469
+ captured.first , {captured.second .front ()}));
1470
+ if (!newInnerBody)
1471
+ return nullptr ;
1460
1472
1473
+ caseStmt->setBody (cast<BraceStmt>(newInnerBody.get ()));
1461
1474
return caseStmt;
1462
1475
}
1463
1476
1464
- Stmt * visitForEachStmt (
1465
- ForEachStmt *forEachStmt, ResultBuilderTarget target) {
1477
+ NullablePtr< Stmt> visitForEachStmt (ForEachStmt *forEachStmt,
1478
+ ResultBuilderTarget target) {
1466
1479
// Translate the for-each loop header.
1467
1480
ConstraintSystem &cs = solution.getConstraintSystem ();
1468
1481
auto forEachTarget =
@@ -1492,13 +1505,14 @@ class BuilderClosureRewriter
1492
1505
// will append the result of executing the loop body to the array.
1493
1506
auto body = forEachStmt->getBody ();
1494
1507
auto capturedBody = takeCapturedStmt (body);
1495
- auto newBody = cast<BraceStmt>(
1496
- visitBraceStmt (
1497
- body,
1498
- ResultBuilderTarget::forExpression (arrayAppendCall),
1499
- ResultBuilderTarget::forAssign (
1500
- capturedBody.first , {capturedBody.second .front ()})));
1501
- forEachStmt->setBody (newBody);
1508
+ auto newBody = visitBraceStmt (
1509
+ body, ResultBuilderTarget::forExpression (arrayAppendCall),
1510
+ ResultBuilderTarget::forAssign (capturedBody.first ,
1511
+ {capturedBody.second .front ()}));
1512
+ if (!newBody)
1513
+ return nullptr ;
1514
+
1515
+ forEachStmt->setBody (cast<BraceStmt>(newBody.get ()));
1502
1516
outerBodySteps.push_back (forEachStmt);
1503
1517
1504
1518
// Step 3. Perform the buildArray() call to turn the array of results
@@ -1510,11 +1524,11 @@ class BuilderClosureRewriter
1510
1524
1511
1525
// Form a brace statement to put together the three main steps for the
1512
1526
// for-each loop translation outlined above.
1513
- return BraceStmt::create (
1514
- ctx, forEachStmt-> getStartLoc (), outerBodySteps, newBody->getEndLoc ());
1527
+ return BraceStmt::create (ctx, forEachStmt-> getStartLoc (), outerBodySteps,
1528
+ newBody. get () ->getEndLoc ());
1515
1529
}
1516
1530
1517
- Stmt * visitThrowStmt (ThrowStmt *throwStmt) {
1531
+ NullablePtr< Stmt> visitThrowStmt (ThrowStmt *throwStmt) {
1518
1532
// Rewrite the error.
1519
1533
auto target = *solution.getConstraintSystem ()
1520
1534
.getSolutionApplicationTarget (throwStmt);
@@ -1526,12 +1540,14 @@ class BuilderClosureRewriter
1526
1540
return throwStmt;
1527
1541
}
1528
1542
1529
- Stmt *visitThrowStmt (ThrowStmt *throwStmt, ResultBuilderTarget target) {
1543
+ NullablePtr<Stmt> visitThrowStmt (ThrowStmt *throwStmt,
1544
+ ResultBuilderTarget target) {
1530
1545
llvm_unreachable (" Throw statements produce no value" );
1531
1546
}
1532
1547
1533
1548
#define UNHANDLED_RESULT_BUILDER_STMT (STMT ) \
1534
- Stmt *visit##STMT##Stmt(STMT##Stmt *stmt, ResultBuilderTarget target) { \
1549
+ NullablePtr<Stmt> \
1550
+ visit##STMT##Stmt(STMT##Stmt *stmt, ResultBuilderTarget target) { \
1535
1551
llvm_unreachable (" Function builders do not allow statement of kind " \
1536
1552
#STMT); \
1537
1553
}
@@ -1563,12 +1579,12 @@ BraceStmt *swift::applyResultBuilderTransform(
1563
1579
rewriteTarget) {
1564
1580
BuilderClosureRewriter rewriter (solution, dc, applied, rewriteTarget);
1565
1581
auto captured = rewriter.takeCapturedStmt (body);
1566
- return cast_or_null<BraceStmt> (
1567
- rewriter. visitBraceStmt (
1568
- body,
1569
- ResultBuilderTarget::forReturn (applied. returnExpr ),
1570
- ResultBuilderTarget::forAssign (
1571
- captured. first , captured. second ) ));
1582
+ auto result = rewriter. visitBraceStmt (
1583
+ body, ResultBuilderTarget::forReturn (applied. returnExpr ),
1584
+ ResultBuilderTarget::forAssign (captured. first , captured. second ));
1585
+ if (!result)
1586
+ return nullptr ;
1587
+ return cast<BraceStmt>(result. get ( ));
1572
1588
}
1573
1589
1574
1590
Optional<BraceStmt *> TypeChecker::applyResultBuilderBodyTransform (
0 commit comments