Skip to content

Commit 5f6ae81

Browse files
authored
Merge pull request swiftlang#63109 from xedin/result-builder-if-else-sequences-5.8
[5.8][BuilderTransform] All `if` sequences without `else` should call `buildOptional`
2 parents 52bcb1e + 9db0066 commit 5f6ae81

File tree

2 files changed

+132
-18
lines changed

2 files changed

+132
-18
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,26 +1255,9 @@ class ResultBuilderTransform
12551255
auto *builderCall =
12561256
buildWrappedChainPayload(branchVarRef, i, numPayloads, isOptional);
12571257

1258-
auto isTopLevel = [&](Stmt *anchor) {
1259-
if (ifStmt->getThenStmt() == anchor)
1260-
return true;
1261-
1262-
// The situation is this:
1263-
//
1264-
// if <cond> {
1265-
// ...
1266-
// } else if <other-cond> {
1267-
// ...
1268-
// }
1269-
if (auto *innerIf = getAsStmt<IfStmt>(ifStmt->getElseStmt()))
1270-
return innerIf->getThenStmt() == anchor;
1271-
1272-
return ifStmt->getElseStmt() == anchor;
1273-
};
1274-
12751258
// The operand should have optional type if we had optional results,
12761259
// so we just need to call `buildIf` now, since we're at the top level.
1277-
if (isOptional && isTopLevel(anchor)) {
1260+
if (isOptional) {
12781261
builderCall = buildCallIfWanted(ifStmt->getThenStmt()->getStartLoc(),
12791262
builder.getBuildOptionalId(),
12801263
builderCall, /*argLabels=*/{});

test/Constraints/result_builder.swift

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,3 +1252,134 @@ do {
12521252
}
12531253
// CHECK: the answer
12541254
}
1255+
1256+
protocol TestIfSequences {
1257+
}
1258+
1259+
struct A: TestIfSequences {}
1260+
struct B: TestIfSequences {}
1261+
struct C: TestIfSequences {}
1262+
struct D: TestIfSequences {}
1263+
1264+
func testOptionalIfElseSequences() {
1265+
func check<T>(_ v: TestIfSequences,
1266+
@TupleBuilder body: (TestIfSequences) throws -> T) rethrows {
1267+
print(try body(v))
1268+
}
1269+
1270+
check(A()) { v in
1271+
if let a = v as? A {
1272+
a
1273+
} else if let b = v as? B {
1274+
b
1275+
} else if let c = v as? C {
1276+
c
1277+
}
1278+
}
1279+
1280+
check(B()) { v in
1281+
if let a = v as? A {
1282+
a
1283+
} else if let b = v as? B {
1284+
b
1285+
} else if let c = v as? C {
1286+
c
1287+
}
1288+
}
1289+
1290+
check(C()) { v in
1291+
if let a = v as? A {
1292+
a
1293+
} else if let b = v as? B {
1294+
b
1295+
} else if let c = v as? C {
1296+
c
1297+
}
1298+
}
1299+
1300+
check(D()) { v in
1301+
if let a = v as? A {
1302+
a
1303+
} else if let b = v as? B {
1304+
b
1305+
} else if let c = v as? C {
1306+
c
1307+
} else {
1308+
D()
1309+
}
1310+
}
1311+
1312+
check(A()) { v in
1313+
if let a = v as? A {
1314+
a
1315+
} else {
1316+
if let b = v as? B {
1317+
b
1318+
}
1319+
1320+
if let c = v as? C {
1321+
c
1322+
} else if let d = v as? D {
1323+
d
1324+
}
1325+
}
1326+
}
1327+
1328+
check(B()) { v in
1329+
if let a = v as? A {
1330+
a
1331+
} else {
1332+
if let b = v as? B {
1333+
b
1334+
}
1335+
1336+
if let c = v as? C {
1337+
c
1338+
} else if let d = v as? D {
1339+
d
1340+
}
1341+
}
1342+
}
1343+
1344+
check(C()) { v in
1345+
if let a = v as? A {
1346+
a
1347+
} else {
1348+
if let b = v as? B {
1349+
b
1350+
}
1351+
1352+
if let c = v as? C {
1353+
c
1354+
} else if let d = v as? D {
1355+
d
1356+
}
1357+
}
1358+
}
1359+
1360+
check(D()) { v in
1361+
if let a = v as? A {
1362+
a
1363+
} else {
1364+
if let b = v as? B {
1365+
b
1366+
}
1367+
1368+
if let c = v as? C {
1369+
c
1370+
} else if let d = v as? D {
1371+
d
1372+
}
1373+
}
1374+
}
1375+
}
1376+
1377+
testOptionalIfElseSequences()
1378+
// CHECK: Optional(main.Either<main.Either<main.A, main.B>, main.C>.first(main.Either<main.A, main.B>.first(main.A())))
1379+
// CHECK-NEXT: Optional(main.Either<main.Either<main.A, main.B>, main.C>.first(main.Either<main.A, main.B>.second(main.B())))
1380+
// CHECK-NEXT: Optional(main.Either<main.Either<main.A, main.B>, main.C>.second(main.C()))
1381+
// CHECK-NEXT: second(main.Either<main.C, main.D>.second(main.D()))
1382+
// CHECK-NEXT: first(main.A())
1383+
// CHECK-NEXT: second(Optional(main.B()), nil)
1384+
// CHECK-NEXT: second(nil, Optional(main.Either<main.C, main.D>.first(main.C())))
1385+
// CHECK-NEXT: second(nil, Optional(main.Either<main.C, main.D>.second(main.D())))

0 commit comments

Comments
 (0)