@@ -25,6 +25,16 @@ using namespace swift::constraints;
2525
2626namespace {
2727
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+
2838// / Find any type variable references inside of an AST node.
2939class TypeVariableRefFinder : public ASTWalker {
3040 ConstraintSystem &CS;
@@ -829,14 +839,9 @@ class ClosureConstraintGenerator
829839 resultExpr = returnStmt->getResult ();
830840 assert (resultExpr && " non-empty result without expression?" );
831841 } else {
832- auto &ctx = closure->getASTContext ();
833842 // If this is simplify `return`, let's create an empty tuple
834843 // 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 ());
840845 }
841846
842847 SolutionApplicationTarget target (resultExpr, closure, CTP_ReturnStmt,
@@ -1283,9 +1288,66 @@ class ClosureConstraintApplication
12831288 }
12841289 }
12851290
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+
12861315 return braceStmt;
12871316 }
12881317
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+
12891351 ASTNode visitReturnStmt (ReturnStmt *returnStmt) {
12901352 if (!returnStmt->hasResult ()) {
12911353 // If contextual is not optional, there is nothing to do here.
0 commit comments