@@ -485,7 +485,7 @@ struct SyntacticElementContext
485
485
}
486
486
}
487
487
488
- bool isSingleExpressionClosure (ConstraintSystem &cs) {
488
+ bool isSingleExpressionClosure (ConstraintSystem &cs) const {
489
489
if (auto ref = getAsAnyFunctionRef ()) {
490
490
if (cs.getAppliedResultBuilderTransform (*ref))
491
491
return false ;
@@ -1242,32 +1242,7 @@ class SyntacticElementConstraintGenerator
1242
1242
}
1243
1243
1244
1244
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
-
1269
1245
Expr *resultExpr;
1270
-
1271
1246
if (returnStmt->hasResult ()) {
1272
1247
resultExpr = returnStmt->getResult ();
1273
1248
assert (resultExpr && " non-empty result without expression?" );
@@ -1279,10 +1254,10 @@ class SyntacticElementConstraintGenerator
1279
1254
resultExpr = getVoidExpr (cs.getASTContext (), returnStmt->getEndLoc ());
1280
1255
}
1281
1256
1282
- auto contextualResultInfo = getContextualResultInfo ();
1257
+ auto contextualResultInfo = getContextualResultInfoFor (returnStmt);
1258
+
1283
1259
SyntacticElementTarget target (resultExpr, context.getAsDeclContext (),
1284
- contextualResultInfo,
1285
- /* isDiscarded=*/ false );
1260
+ contextualResultInfo, /* isDiscarded=*/ false );
1286
1261
1287
1262
if (cs.generateConstraints (target)) {
1288
1263
hadError = true ;
@@ -1327,7 +1302,7 @@ class SyntacticElementConstraintGenerator
1327
1302
createConjunction ({resultElt}, locator);
1328
1303
}
1329
1304
1330
- ContextualTypeInfo getContextualResultInfo ( ) const {
1305
+ ContextualTypeInfo getContextualResultInfoFor (ReturnStmt *returnStmt ) const {
1331
1306
auto funcRef = AnyFunctionRef::fromDeclContext (context.getAsDeclContext ());
1332
1307
if (!funcRef)
1333
1308
return {Type (), CTP_Unused};
@@ -1336,8 +1311,18 @@ class SyntacticElementConstraintGenerator
1336
1311
return {transform->bodyResultType , CTP_ReturnStmt};
1337
1312
1338
1313
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
+ }
1341
1326
1342
1327
return {funcRef->getBodyResultType (), CTP_ReturnStmt};
1343
1328
}
@@ -2155,22 +2140,15 @@ class SyntacticElementSolutionApplication
2155
2140
mode = convertToResult;
2156
2141
}
2157
2142
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)) {
2174
2152
resultExpr = newResultTarget->getAsExpr ();
2175
2153
}
2176
2154
0 commit comments