@@ -769,30 +769,57 @@ class ClosureConstraintGenerator
769
769
}
770
770
771
771
void visitReturnStmt (ReturnStmt *returnStmt) {
772
- Type resultType ;
772
+ auto contextualTy = cs. getClosureType (closure)-> getResult () ;
773
773
774
- if (returnStmt->hasResult ()) {
774
+ // Single-expression closures are effectively a `return` statement,
775
+ // so let's give them a special locator as to indicate that.
776
+ if (closure->hasSingleExpressionBody ()) {
775
777
auto *expr = returnStmt->getResult ();
776
- assert (expr && " non-empty result without expression?" );
778
+ assert (expr && " single expression closure without expression?" );
777
779
778
- // FIXME: Use SolutionApplicationTarget?
779
780
expr = cs.generateConstraints (expr, closure, /* isInputExpression=*/ false );
780
781
if (!expr) {
781
782
hadError = true ;
782
783
return ;
783
784
}
784
785
785
- resultType = cs.getType (expr);
786
+ cs.addConstraint (
787
+ ConstraintKind::Conversion, cs.getType (expr), contextualTy,
788
+ cs.getConstraintLocator (
789
+ closure, LocatorPathElt::ClosureBody (
790
+ /* hasReturn=*/ !returnStmt->isImplicit ())));
791
+ return ;
792
+ }
793
+
794
+ Expr *resultExpr;
795
+
796
+ if (returnStmt->hasResult ()) {
797
+ resultExpr = returnStmt->getResult ();
798
+ assert (resultExpr && " non-empty result without expression?" );
786
799
} else {
787
- resultType = cs.getASTContext ().getVoidDecl ()->getDeclaredInterfaceType ();
800
+ auto &ctx = closure->getASTContext ();
801
+ // If this is simplify `return`, let's create an empty tuple
802
+ // which is also useful if contextual turns out to be e.g. `Void?`.
803
+ resultExpr = TupleExpr::createEmpty (ctx,
804
+ /* LParenLoc=*/ SourceLoc (),
805
+ /* RParenLoc=*/ SourceLoc (),
806
+ /* Implicit=*/ true );
807
+ resultExpr->setType (ctx.TheEmptyTupleType );
788
808
}
789
809
790
- // FIXME: Locator should point at the return statement?
791
- bool hasReturn = hasExplicitResult (closure);
792
- cs.addConstraint (ConstraintKind::Conversion, resultType,
793
- cs.getClosureType (closure)->getResult (),
794
- cs.getConstraintLocator (
795
- closure, LocatorPathElt::ClosureBody (hasReturn)));
810
+ SolutionApplicationTarget target (resultExpr, closure, CTP_ReturnStmt,
811
+ contextualTy,
812
+ /* isDiscarded=*/ false );
813
+
814
+ // FIXME: Use SolutionApplicationTarget?
815
+ if (cs.generateConstraints (target, FreeTypeVariableBinding::Disallow)) {
816
+ hadError = true ;
817
+ return ;
818
+ }
819
+
820
+ cs.setContextualType (target.getAsExpr (), TypeLoc::withoutLoc (contextualTy),
821
+ CTP_ReturnStmt);
822
+ cs.setSolutionApplicationTarget (returnStmt, target);
796
823
}
797
824
798
825
bool isSupportedMultiStatementClosure () const {
@@ -1205,33 +1232,23 @@ class ClosureConstraintApplication
1205
1232
1206
1233
ASTNode visitReturnStmt (ReturnStmt *returnStmt) {
1207
1234
if (!returnStmt->hasResult ()) {
1235
+ // If contextual is not optional, there is nothing to do here.
1236
+ if (resultType->isVoid ())
1237
+ return returnStmt;
1238
+
1208
1239
// It's possible to infer e.g. `Void?` for cases where
1209
1240
// `return` doesn't have an expression. If contextual
1210
1241
// type is `Void` wrapped into N optional types, let's
1211
1242
// add an implicit `()` expression and let it be injected
1212
1243
// into optional required number of times.
1213
- auto &ctx = closure->getASTContext ();
1214
-
1215
- // If contextual is not optional, there is nothing to do here.
1216
- if (resultType->isVoid ())
1217
- return returnStmt;
1218
1244
1219
1245
assert (resultType->getOptionalObjectType () &&
1220
1246
resultType->lookThroughAllOptionalTypes ()->isVoid ());
1221
1247
1222
1248
auto &cs = solution.getConstraintSystem ();
1223
1249
1224
- // Build an implicit empty tuple to represent `Void` return
1225
- auto *emptyTuple = TupleExpr::createEmpty (ctx,
1226
- /* LParenLoc=*/ SourceLoc (),
1227
- /* RParenLoc=*/ SourceLoc (),
1228
- /* Implicit=*/ true );
1229
- emptyTuple->setType (ctx.TheEmptyTupleType );
1230
- // Cache the type of this new expression in the constraint system
1231
- // for the future reference.
1232
- cs.cacheExprTypes (emptyTuple);
1233
-
1234
- returnStmt->setResult (emptyTuple);
1250
+ auto target = *cs.getSolutionApplicationTarget (returnStmt);
1251
+ returnStmt->setResult (target.getAsExpr ());
1235
1252
}
1236
1253
1237
1254
auto *resultExpr = returnStmt->getResult ();
0 commit comments