@@ -1066,7 +1066,7 @@ class ResultBuilderTransform
1066
1066
return None;
1067
1067
}
1068
1068
1069
- std::pair<NullablePtr<VarDecl >, Optional<UnsupportedElt>>
1069
+ std::pair<NullablePtr<Expr >, Optional<UnsupportedElt>>
1070
1070
transform (BraceStmt *braceStmt, SmallVectorImpl<ASTNode> &newBody) {
1071
1071
SmallVector<Expr *, 4 > buildBlockArguments;
1072
1072
@@ -1082,7 +1082,6 @@ class ResultBuilderTransform
1082
1082
}
1083
1083
1084
1084
// Synthesize `buildBlock` or `buildPartial` based on captured arguments.
1085
- NullablePtr<VarDecl> buildBlockVar;
1086
1085
{
1087
1086
// If the builder supports `buildPartialBlock(first:)` and
1088
1087
// `buildPartialBlock(accumulated:next:)`, use this to combine
@@ -1097,16 +1096,19 @@ class ResultBuilderTransform
1097
1096
{buildBlockArguments.front ()},
1098
1097
/* argLabels=*/ {ctx.Id_first });
1099
1098
1100
- buildBlockVar = captureExpr (buildPartialFirst, newBody);
1099
+ auto * buildBlockVar = captureExpr (buildPartialFirst, newBody);
1101
1100
1102
1101
for (auto *argExpr : llvm::drop_begin (buildBlockArguments)) {
1103
1102
auto *accumPartialBlock = builder.buildCall (
1104
1103
braceStmt->getStartLoc (), ctx.Id_buildPartialBlock ,
1105
- {builder.buildVarRef (buildBlockVar. get () , argExpr->getStartLoc ()),
1104
+ {builder.buildVarRef (buildBlockVar, argExpr->getStartLoc ()),
1106
1105
argExpr},
1107
1106
{ctx.Id_accumulated , ctx.Id_next });
1108
1107
buildBlockVar = captureExpr (accumPartialBlock, newBody);
1109
1108
}
1109
+
1110
+ return std::make_pair (
1111
+ builder.buildVarRef (buildBlockVar, braceStmt->getStartLoc ()), None);
1110
1112
}
1111
1113
// If `buildBlock` does not exist at this point, it could be the case that
1112
1114
// `buildPartialBlock` did not have the sufficient availability for this
@@ -1118,17 +1120,14 @@ class ResultBuilderTransform
1118
1120
builder.getType ());
1119
1121
return failTransform (braceStmt);
1120
1122
}
1123
+
1121
1124
// Otherwise, call `buildBlock` on all subexpressions.
1122
- else {
1123
- // Call Builder.buildBlock(... args ...)
1124
- auto *buildBlock = builder.buildCall (
1125
- braceStmt->getStartLoc (), ctx.Id_buildBlock , buildBlockArguments,
1126
- /* argLabels=*/ {});
1127
- buildBlockVar = captureExpr (buildBlock, newBody);
1128
- }
1125
+ // Call Builder.buildBlock(... args ...)
1126
+ auto *buildBlock = builder.buildCall (
1127
+ braceStmt->getStartLoc (), ctx.Id_buildBlock , buildBlockArguments,
1128
+ /* argLabels=*/ {});
1129
+ return std::make_pair (buildBlock, None);
1129
1130
}
1130
-
1131
- return std::make_pair (buildBlockVar.get (), None);
1132
1131
}
1133
1132
1134
1133
std::pair<bool , UnsupportedElt>
@@ -1141,10 +1140,10 @@ class ResultBuilderTransform
1141
1140
return std::make_pair (true , element);
1142
1141
};
1143
1142
1144
- NullablePtr<VarDecl> buildBlockVar ;
1143
+ NullablePtr<Expr> buildBlockVarRef ;
1145
1144
Optional<UnsupportedElt> unsupported;
1146
1145
1147
- std::tie (buildBlockVar , unsupported) = transform (braceStmt, elements);
1146
+ std::tie (buildBlockVarRef , unsupported) = transform (braceStmt, elements);
1148
1147
if (unsupported)
1149
1148
return failure (*unsupported);
1150
1149
@@ -1156,14 +1155,12 @@ class ResultBuilderTransform
1156
1155
// are attached to the beginning of the brace instead of its end.
1157
1156
auto resultLoc = braceStmt->getStartLoc ();
1158
1157
if (bodyVar) {
1159
- elements.push_back (new (ctx) AssignExpr (
1160
- builder.buildVarRef (bodyVar.get (), resultLoc),
1161
- /* EqualLoc=*/ SourceLoc (),
1162
- builder.buildVarRef (buildBlockVar.get (), resultLoc),
1163
- /* Implicit=*/ true ));
1158
+ elements.push_back (
1159
+ new (ctx) AssignExpr (builder.buildVarRef (bodyVar.get (), resultLoc),
1160
+ /* EqualLoc=*/ SourceLoc (), buildBlockVarRef.get (),
1161
+ /* Implicit=*/ true ));
1164
1162
} else {
1165
- Expr *buildBlockResult =
1166
- builder.buildVarRef (buildBlockVar.get (), resultLoc);
1163
+ Expr *buildBlockResult = buildBlockVarRef.get ();
1167
1164
// Otherwise, it's a top-level brace and we need to synthesize
1168
1165
// a call to `buildFialBlock` if supported.
1169
1166
if (builder.supports (ctx.Id_buildFinalResult , {Identifier ()})) {
@@ -1220,9 +1217,9 @@ class ResultBuilderTransform
1220
1217
if (!isBuildableIfChain (ifStmt, numPayloads, isOptional))
1221
1218
return failTransform (ifStmt);
1222
1219
1223
- SmallVector<std::pair<VarDecl *, Stmt *>, 4 > branchVars ;
1220
+ SmallVector<std::pair<Expr *, Stmt *>, 4 > branchVarRefs ;
1224
1221
1225
- auto transformed = transformIf (ifStmt, branchVars );
1222
+ auto transformed = transformIf (ifStmt, branchVarRefs );
1226
1223
if (!transformed)
1227
1224
return failTransform (ifStmt);
1228
1225
@@ -1236,17 +1233,15 @@ class ResultBuilderTransform
1236
1233
// `if` goes first.
1237
1234
doBody.push_back (ifStmt);
1238
1235
1239
- assert (numPayloads == branchVars .size ());
1236
+ assert (numPayloads == branchVarRefs .size ());
1240
1237
1241
1238
SmallVector<Expr *, 4 > buildEitherCalls;
1242
1239
for (unsigned i = 0 ; i != numPayloads; i++) {
1243
- VarDecl *branchVar ;
1240
+ Expr *branchVarRef ;
1244
1241
Stmt *anchor;
1245
1242
1246
- std::tie (branchVar , anchor) = branchVars [i];
1243
+ std::tie (branchVarRef , anchor) = branchVarRefs [i];
1247
1244
1248
- auto *branchVarRef =
1249
- builder.buildVarRef (branchVar, ifStmt->getEndLoc ());
1250
1245
auto *builderCall =
1251
1246
buildWrappedChainPayload (branchVarRef, i, numPayloads, isOptional);
1252
1247
@@ -1308,7 +1303,7 @@ class ResultBuilderTransform
1308
1303
1309
1304
NullablePtr<IfStmt>
1310
1305
transformIf (IfStmt *ifStmt,
1311
- SmallVectorImpl<std::pair<VarDecl *, Stmt *>> &branchVars ) {
1306
+ SmallVectorImpl<std::pair<Expr *, Stmt *>> &branchVarRefs ) {
1312
1307
Optional<UnsupportedElt> unsupported;
1313
1308
1314
1309
// If there is a #available in the condition, wrap the 'then' or 'else'
@@ -1317,42 +1312,40 @@ class ResultBuilderTransform
1317
1312
bool supportsAvailability =
1318
1313
availabilityCond && builder.supports (ctx.Id_buildLimitedAvailability );
1319
1314
1320
- NullablePtr<VarDecl> thenVar ;
1315
+ NullablePtr<Expr> thenVarRef ;
1321
1316
NullablePtr<Stmt> thenBranch;
1322
1317
{
1323
1318
SmallVector<ASTNode, 4 > thenBody;
1324
1319
1325
1320
auto *ifBraceStmt = cast<BraceStmt>(ifStmt->getThenStmt ());
1326
1321
1327
- std::tie (thenVar , unsupported) = transform (ifBraceStmt, thenBody);
1322
+ std::tie (thenVarRef , unsupported) = transform (ifBraceStmt, thenBody);
1328
1323
if (unsupported) {
1329
1324
recordUnsupported (*unsupported);
1330
1325
return nullptr ;
1331
1326
}
1332
1327
1333
1328
if (supportsAvailability &&
1334
1329
!availabilityCond->getAvailability ()->isUnavailability ()) {
1335
- auto *thenVarRef =
1336
- builder.buildVarRef (thenVar.get (), ifBraceStmt->getEndLoc ());
1337
-
1338
1330
auto *builderCall = buildCallIfWanted (
1339
- ifStmt-> getThenStmt ()-> getEndLoc (), ctx.Id_buildLimitedAvailability ,
1340
- {thenVarRef}, {Identifier ()});
1331
+ ifBraceStmt-> getStartLoc (), ctx.Id_buildLimitedAvailability ,
1332
+ {thenVarRef. get () }, {Identifier ()});
1341
1333
1342
- thenVar = captureExpr (builderCall, thenBody);
1334
+ thenVarRef = builder.buildVarRef (captureExpr (builderCall, thenBody),
1335
+ ifBraceStmt->getStartLoc ());
1343
1336
}
1344
1337
1345
1338
thenBranch = cloneBraceWith (ifBraceStmt, thenBody);
1346
- branchVars .push_back ({thenVar .get (), thenBranch.get ()});
1339
+ branchVarRefs .push_back ({thenVarRef .get (), thenBranch.get ()});
1347
1340
}
1348
1341
1349
1342
NullablePtr<Stmt> elseBranch;
1350
1343
1351
1344
if (auto *elseStmt = ifStmt->getElseStmt ()) {
1352
- NullablePtr<VarDecl> elseVar ;
1345
+ NullablePtr<Expr> elseVarRef ;
1353
1346
1354
1347
if (auto *innerIfStmt = getAsStmt<IfStmt>(elseStmt)) {
1355
- elseBranch = transformIf (innerIfStmt, branchVars );
1348
+ elseBranch = transformIf (innerIfStmt, branchVarRefs );
1356
1349
if (!elseBranch) {
1357
1350
recordUnsupported (innerIfStmt);
1358
1351
return nullptr ;
@@ -1361,7 +1354,7 @@ class ResultBuilderTransform
1361
1354
auto *elseBraceStmt = cast<BraceStmt>(elseStmt);
1362
1355
SmallVector<ASTNode> elseBody;
1363
1356
1364
- std::tie (elseVar , unsupported) = transform (elseBraceStmt, elseBody);
1357
+ std::tie (elseVarRef , unsupported) = transform (elseBraceStmt, elseBody);
1365
1358
if (unsupported) {
1366
1359
recordUnsupported (*unsupported);
1367
1360
return nullptr ;
@@ -1371,18 +1364,16 @@ class ResultBuilderTransform
1371
1364
// call to buildLimitedAvailability(_:).
1372
1365
if (supportsAvailability &&
1373
1366
availabilityCond->getAvailability ()->isUnavailability ()) {
1374
- auto *elseVarRef =
1375
- builder.buildVarRef (elseVar.get (), elseBraceStmt->getEndLoc ());
1376
-
1377
- auto *builderCall = buildCallIfWanted (elseBraceStmt->getStartLoc (),
1378
- ctx.Id_buildLimitedAvailability ,
1379
- {elseVarRef}, {Identifier ()});
1367
+ auto *builderCall = buildCallIfWanted (
1368
+ elseBraceStmt->getStartLoc (), ctx.Id_buildLimitedAvailability ,
1369
+ {elseVarRef.get ()}, {Identifier ()});
1380
1370
1381
- elseVar = captureExpr (builderCall, elseBody);
1371
+ elseVarRef = builder.buildVarRef (captureExpr (builderCall, elseBody),
1372
+ elseBraceStmt->getStartLoc ());
1382
1373
}
1383
1374
1384
1375
elseBranch = cloneBraceWith (elseBraceStmt, elseBody);
1385
- branchVars .push_back ({elseVar .get (), elseBranch.get ()});
1376
+ branchVarRefs .push_back ({elseVarRef .get (), elseBranch.get ()});
1386
1377
}
1387
1378
}
1388
1379
@@ -1404,23 +1395,23 @@ class ResultBuilderTransform
1404
1395
SmallVector<ASTNode, 4 > doBody;
1405
1396
1406
1397
SmallVector<ASTNode, 4 > cases;
1407
- SmallVector<VarDecl *, 4 > caseVars ;
1398
+ SmallVector<Expr *, 4 > caseVarRefs ;
1408
1399
1409
1400
for (auto *caseStmt : switchStmt->getCases ()) {
1410
1401
auto transformed = transformCase (caseStmt);
1411
1402
if (!transformed)
1412
1403
return failTransform (caseStmt);
1413
1404
1414
1405
cases.push_back (transformed->second );
1415
- caseVars .push_back (transformed->first );
1406
+ caseVarRefs .push_back (transformed->first );
1416
1407
}
1417
1408
1418
1409
// If there are no 'case' statements in the body let's try
1419
1410
// to diagnose this situation via limited exhaustiveness check
1420
1411
// before failing a builder transform, otherwise type-checker
1421
1412
// might end up without any diagnostics which leads to crashes
1422
1413
// in SILGen.
1423
- if (caseVars .empty ()) {
1414
+ if (caseVarRefs .empty ()) {
1424
1415
TypeChecker::checkSwitchExhaustiveness (switchStmt, dc,
1425
1416
/* limitChecking=*/ true );
1426
1417
return failTransform (switchStmt);
@@ -1434,15 +1425,13 @@ class ResultBuilderTransform
1434
1425
doBody.push_back (transformedSwitch);
1435
1426
1436
1427
SmallVector<Expr *, 4 > injectedExprs;
1437
- for (auto idx : indices (caseVars)) {
1438
- auto caseStmt = cases[idx];
1439
- auto *caseVar = caseVars[idx];
1428
+ for (auto idx : indices (caseVarRefs)) {
1429
+ auto *caseVarRef = caseVarRefs[idx];
1440
1430
1441
1431
// Build the expression that injects the case variable into appropriate
1442
1432
// buildEither(first:)/buildEither(second:) chain.
1443
- Expr *caseVarRef = builder.buildVarRef (caseVar, caseStmt.getEndLoc ());
1444
1433
Expr *injectedCaseExpr = buildWrappedChainPayload (
1445
- caseVarRef, idx, caseVars .size (), /* isOptional=*/ false );
1434
+ caseVarRef, idx, caseVarRefs .size (), /* isOptional=*/ false );
1446
1435
1447
1436
injectedExprs.push_back (injectedCaseExpr);
1448
1437
}
@@ -1454,7 +1443,7 @@ class ResultBuilderTransform
1454
1443
return DoStmt::createImplicit (ctx, LabeledStmtInfo (), doBody);
1455
1444
}
1456
1445
1457
- Optional<std::pair<VarDecl *, CaseStmt *>> transformCase (CaseStmt *caseStmt) {
1446
+ Optional<std::pair<Expr *, CaseStmt *>> transformCase (CaseStmt *caseStmt) {
1458
1447
auto *body = caseStmt->getBody ();
1459
1448
1460
1449
// Explicitly disallow `case` statements with empty bodies
@@ -1470,11 +1459,11 @@ class ResultBuilderTransform
1470
1459
}
1471
1460
}
1472
1461
1473
- NullablePtr<VarDecl> caseVar ;
1462
+ NullablePtr<Expr> caseVarRef ;
1474
1463
Optional<UnsupportedElt> unsupported;
1475
1464
SmallVector<ASTNode, 4 > newBody;
1476
1465
1477
- std::tie (caseVar , unsupported) = transform (body, newBody);
1466
+ std::tie (caseVarRef , unsupported) = transform (body, newBody);
1478
1467
1479
1468
if (unsupported) {
1480
1469
recordUnsupported (*unsupported);
@@ -1489,7 +1478,7 @@ class ResultBuilderTransform
1489
1478
caseStmt->getCaseBodyVariablesOrEmptyArray (), caseStmt->isImplicit (),
1490
1479
caseStmt->getFallthroughStmt ());
1491
1480
1492
- return std::make_pair (caseVar .get (), newCase);
1481
+ return std::make_pair (caseVarRef .get (), newCase);
1493
1482
}
1494
1483
1495
1484
// / do {
@@ -1533,12 +1522,12 @@ class ResultBuilderTransform
1533
1522
ArrayExpr::create (ctx, /* LBrace=*/ endLoc, /* Elements=*/ {},
1534
1523
/* Commas=*/ {}, /* RBrace=*/ endLoc));
1535
1524
1536
- NullablePtr<VarDecl> bodyVar ;
1525
+ NullablePtr<Expr> bodyVarRef ;
1537
1526
Optional<UnsupportedElt> unsupported;
1538
1527
1539
1528
SmallVector<ASTNode, 4 > newBody;
1540
1529
{
1541
- std::tie (bodyVar , unsupported) =
1530
+ std::tie (bodyVarRef , unsupported) =
1542
1531
transform (forEachStmt->getBody (), newBody);
1543
1532
if (unsupported)
1544
1533
return failTransform (*unsupported);
@@ -1552,9 +1541,8 @@ class ResultBuilderTransform
1552
1541
DeclNameLoc (endLoc), /* implicit=*/ true );
1553
1542
arrayAppendRef->setFunctionRefKind (FunctionRefKind::SingleApply);
1554
1543
1555
- auto bodyVarRef = builder.buildVarRef (bodyVar.get (), endLoc);
1556
1544
auto *argList = ArgumentList::createImplicit (
1557
- ctx, endLoc, {Argument::unlabeled (bodyVarRef)}, endLoc);
1545
+ ctx, endLoc, {Argument::unlabeled (bodyVarRef. get () )}, endLoc);
1558
1546
1559
1547
newBody.push_back (
1560
1548
CallExpr::createImplicit (ctx, arrayAppendRef, argList));
0 commit comments