@@ -485,7 +485,7 @@ struct SyntacticElementContext
485485 }
486486 }
487487
488- bool isSingleExpressionClosure (ConstraintSystem &cs) {
488+ bool isSingleExpressionClosure (ConstraintSystem &cs) const {
489489 if (auto ref = getAsAnyFunctionRef ()) {
490490 if (cs.getAppliedResultBuilderTransform (*ref))
491491 return false ;
@@ -1242,32 +1242,7 @@ class SyntacticElementConstraintGenerator
12421242 }
12431243
12441244 void visitReturnStmt (ReturnStmt *returnStmt) {
1245- // Single-expression closures are effectively a `return` statement,
1246- // so let's give them a special locator as to indicate that.
1247- // Return statements might not have a result if we have a closure whose
1248- // implicit returned value is coerced to Void.
1249- if (context.isSingleExpressionClosure (cs) && returnStmt->hasResult ()) {
1250- auto *expr = returnStmt->getResult ();
1251- assert (expr && " single expression closure without expression?" );
1252-
1253- expr = cs.generateConstraints (expr, context.getAsDeclContext ());
1254- if (!expr) {
1255- hadError = true ;
1256- return ;
1257- }
1258-
1259- auto contextualResultInfo = getContextualResultInfo ();
1260- cs.addConstraint (ConstraintKind::Conversion, cs.getType (expr),
1261- contextualResultInfo.getType (),
1262- cs.getConstraintLocator (
1263- context.getAsAbstractClosureExpr ().get (),
1264- LocatorPathElt::ClosureBody (
1265- /* hasImpliedReturn=*/ returnStmt->isImplied ())));
1266- return ;
1267- }
1268-
12691245 Expr *resultExpr;
1270-
12711246 if (returnStmt->hasResult ()) {
12721247 resultExpr = returnStmt->getResult ();
12731248 assert (resultExpr && " non-empty result without expression?" );
@@ -1279,10 +1254,10 @@ class SyntacticElementConstraintGenerator
12791254 resultExpr = getVoidExpr (cs.getASTContext (), returnStmt->getEndLoc ());
12801255 }
12811256
1282- auto contextualResultInfo = getContextualResultInfo ();
1257+ auto contextualResultInfo = getContextualResultInfoFor (returnStmt);
1258+
12831259 SyntacticElementTarget target (resultExpr, context.getAsDeclContext (),
1284- contextualResultInfo,
1285- /* isDiscarded=*/ false );
1260+ contextualResultInfo, /* isDiscarded=*/ false );
12861261
12871262 if (cs.generateConstraints (target)) {
12881263 hadError = true ;
@@ -1327,7 +1302,7 @@ class SyntacticElementConstraintGenerator
13271302 createConjunction ({resultElt}, locator);
13281303 }
13291304
1330- ContextualTypeInfo getContextualResultInfo ( ) const {
1305+ ContextualTypeInfo getContextualResultInfoFor (ReturnStmt *returnStmt ) const {
13311306 auto funcRef = AnyFunctionRef::fromDeclContext (context.getAsDeclContext ());
13321307 if (!funcRef)
13331308 return {Type (), CTP_Unused};
@@ -1336,8 +1311,18 @@ class SyntacticElementConstraintGenerator
13361311 return {transform->bodyResultType , CTP_ReturnStmt};
13371312
13381313 if (auto *closure =
1339- getAsExpr<ClosureExpr>(funcRef->getAbstractClosureExpr ()))
1340- return {cs.getClosureType (closure)->getResult (), CTP_ClosureResult};
1314+ getAsExpr<ClosureExpr>(funcRef->getAbstractClosureExpr ())) {
1315+ // Single-expression closures need their contextual type locator anchored
1316+ // on the closure itself. Otherwise we use the default contextual type
1317+ // locator, which will be created for us.
1318+ ConstraintLocator *loc = nullptr ;
1319+ if (context.isSingleExpressionClosure (cs) && returnStmt->hasResult ()) {
1320+ loc = cs.getConstraintLocator (
1321+ closure, {LocatorPathElt::ClosureBody (
1322+ /* hasImpliedReturn=*/ returnStmt->isImplied ())});
1323+ }
1324+ return {cs.getClosureType (closure)->getResult (), CTP_ClosureResult, loc};
1325+ }
13411326
13421327 return {funcRef->getBodyResultType (), CTP_ReturnStmt};
13431328 }
@@ -2155,22 +2140,15 @@ class SyntacticElementSolutionApplication
21552140 mode = convertToResult;
21562141 }
21572142
2158- llvm::Optional<SyntacticElementTarget> resultTarget;
2159- if (auto target = cs.getTargetFor (returnStmt)) {
2160- resultTarget = *target;
2161- } else {
2162- // Single-expression closures have to handle returns in a special
2163- // way so the target has to be created for them during solution
2164- // application based on the resolved type.
2165- assert (context.isSingleExpressionClosure (cs));
2166- resultTarget = SyntacticElementTarget (
2167- resultExpr, context.getAsDeclContext (),
2168- mode == convertToResult ? CTP_ClosureResult : CTP_Unused,
2169- mode == convertToResult ? resultType : Type (),
2170- /* isDiscarded=*/ false );
2171- }
2172-
2173- if (auto newResultTarget = rewriteTarget (*resultTarget)) {
2143+ auto target = *cs.getTargetFor (returnStmt);
2144+
2145+ // If we're not converting to a result, unset the contextual type.
2146+ if (mode != convertToResult) {
2147+ target.setExprConversionType (Type ());
2148+ target.setExprContextualTypePurpose (CTP_Unused);
2149+ }
2150+
2151+ if (auto newResultTarget = rewriteTarget (target)) {
21742152 resultExpr = newResultTarget->getAsExpr ();
21752153 }
21762154
0 commit comments