@@ -25,6 +25,16 @@ using namespace swift::constraints;
25
25
26
26
namespace {
27
27
28
+ // Produce an implicit empty tuple expression.
29
+ Expr *getVoidExpr (ASTContext &ctx) {
30
+ auto *voidExpr = TupleExpr::createEmpty (ctx,
31
+ /* LParenLoc=*/ SourceLoc (),
32
+ /* RParenLoc=*/ SourceLoc (),
33
+ /* Implicit=*/ true );
34
+ voidExpr->setType (ctx.TheEmptyTupleType );
35
+ return voidExpr;
36
+ }
37
+
28
38
// / Find any type variable references inside of an AST node.
29
39
class TypeVariableRefFinder : public ASTWalker {
30
40
ConstraintSystem &CS;
@@ -829,14 +839,9 @@ class ClosureConstraintGenerator
829
839
resultExpr = returnStmt->getResult ();
830
840
assert (resultExpr && " non-empty result without expression?" );
831
841
} else {
832
- auto &ctx = closure->getASTContext ();
833
842
// If this is simplify `return`, let's create an empty tuple
834
843
// which is also useful if contextual turns out to be e.g. `Void?`.
835
- resultExpr = TupleExpr::createEmpty (ctx,
836
- /* LParenLoc=*/ SourceLoc (),
837
- /* RParenLoc=*/ SourceLoc (),
838
- /* Implicit=*/ true );
839
- resultExpr->setType (ctx.TheEmptyTupleType );
844
+ resultExpr = getVoidExpr (closure->getASTContext ());
840
845
}
841
846
842
847
SolutionApplicationTarget target (resultExpr, closure, CTP_ReturnStmt,
@@ -1283,9 +1288,66 @@ class ClosureConstraintApplication
1283
1288
}
1284
1289
}
1285
1290
1291
+ // Source compatibility workaround.
1292
+ //
1293
+ // func test<T>(_: () -> T?) {
1294
+ // ...
1295
+ // }
1296
+ //
1297
+ // A multi-statement closure passed to `test` that has an optional
1298
+ // `Void` result type inferred from the body allows:
1299
+ // - empty `return`(s);
1300
+ // - to skip `return nil` or `return ()` at the end.
1301
+ //
1302
+ // Implicit `return ()` has to be inserted as the last element
1303
+ // of the body if there is none. This wasn't needed before SE-0326
1304
+ // because result type was (incorrectly) inferred as `Void` due to
1305
+ // the body being skipped.
1306
+ if (!closure->hasSingleExpressionBody () &&
1307
+ closure->getBody () == braceStmt) {
1308
+ if (resultType->getOptionalObjectType () &&
1309
+ resultType->lookThroughAllOptionalTypes ()->isVoid () &&
1310
+ !braceStmt->getLastElement ().isStmt (StmtKind::Return)) {
1311
+ return addImplicitVoidReturn (braceStmt);
1312
+ }
1313
+ }
1314
+
1286
1315
return braceStmt;
1287
1316
}
1288
1317
1318
+ ASTNode addImplicitVoidReturn (BraceStmt *braceStmt) {
1319
+ auto &ctx = closure->getASTContext ();
1320
+ auto &cs = solution.getConstraintSystem ();
1321
+
1322
+ auto *resultExpr = getVoidExpr (ctx);
1323
+ cs.cacheExprTypes (resultExpr);
1324
+
1325
+ auto *returnStmt = new (ctx) ReturnStmt (SourceLoc (), resultExpr,
1326
+ /* implicit=*/ true );
1327
+
1328
+ // For a target for newly created result and apply a solution
1329
+ // to it, to make sure that optional injection happens required
1330
+ // number of times.
1331
+ {
1332
+ SolutionApplicationTarget target (resultExpr, closure, CTP_ReturnStmt,
1333
+ resultType,
1334
+ /* isDiscarded=*/ false );
1335
+ cs.setSolutionApplicationTarget (returnStmt, target);
1336
+
1337
+ visitReturnStmt (returnStmt);
1338
+ }
1339
+
1340
+ // Re-create brace statement with an additional `return` at the end.
1341
+
1342
+ SmallVector<ASTNode, 4 > elements;
1343
+ elements.append (braceStmt->getElements ().begin (),
1344
+ braceStmt->getElements ().end ());
1345
+ elements.push_back (returnStmt);
1346
+
1347
+ return BraceStmt::create (ctx, braceStmt->getLBraceLoc (), elements,
1348
+ braceStmt->getRBraceLoc ());
1349
+ }
1350
+
1289
1351
ASTNode visitReturnStmt (ReturnStmt *returnStmt) {
1290
1352
if (!returnStmt->hasResult ()) {
1291
1353
// If contextual is not optional, there is nothing to do here.
@@ -1473,11 +1535,13 @@ bool ConstraintSystem::applySolutionToBody(Solution &solution,
1473
1535
auto closureType = cs.getType (closure)->castTo <FunctionType>();
1474
1536
ClosureConstraintApplication application (
1475
1537
solution, closure, closureType->getResult (), rewriteTarget);
1476
- application.visit (closure->getBody ());
1538
+ auto body = application.visit (closure->getBody ());
1477
1539
1478
- if (application.hadError )
1540
+ if (!body || application.hadError )
1479
1541
return true ;
1480
1542
1543
+ closure->setBody (cast<BraceStmt>(body.get <Stmt *>()),
1544
+ closure->hasSingleExpressionBody ());
1481
1545
closure->setBodyState (ClosureExpr::BodyState::TypeCheckedWithSignature);
1482
1546
return false ;
1483
1547
}
0 commit comments