Skip to content

Commit b23f1c2

Browse files
committed
[CSApply] Adjust contextual locator of single expression closure before coercion
Contextual conversion constraint is placed on `result of closure body` and solution application logic should match that.
1 parent af7b722 commit b23f1c2

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

lib/Sema/CSApply.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6792,7 +6792,12 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
67926792
case ConversionRestrictionKind::DoubleToCGFloat: {
67936793
auto conversionKind = knownRestriction->second;
67946794

6795-
auto *argExpr = locator.trySimplifyToExpr();
6795+
// If conversion wraps the whole body of a single-expression closure,
6796+
// let's use the passed-in expression since the closure itself doesn't
6797+
// get updated until coercion is done.
6798+
auto *argExpr = locator.endsWith<LocatorPathElt::ClosureBody>()
6799+
? expr
6800+
: locator.trySimplifyToExpr();
67966801
assert(argExpr);
67976802

67986803
// Source requires implicit conversion to match destination
@@ -9081,11 +9086,28 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
90819086
// If we're supposed to convert the expression to some particular type,
90829087
// do so now.
90839088
if (shouldCoerceToContextualType()) {
9089+
ConstraintLocator *locator = nullptr;
9090+
// Bodies of single-expression closures use a special locator
9091+
// for contextual type conversion to make sure that result is
9092+
// convertible to `Void` when `return` is not used explicitly.
9093+
if (target.getExprContextualTypePurpose() == CTP_ClosureResult) {
9094+
auto *closure = cast<ClosureExpr>(target.getDeclContext());
9095+
auto *returnStmt =
9096+
castToStmt<ReturnStmt>(closure->getBody()->getLastElement());
9097+
9098+
locator = cs.getConstraintLocator(
9099+
closure, LocatorPathElt::ClosureBody(
9100+
/*hasReturn=*/!returnStmt->isImplicit()));
9101+
} else {
9102+
locator = cs.getConstraintLocator(
9103+
resultExpr, LocatorPathElt::ContextualType(
9104+
target.getExprContextualTypePurpose()));
9105+
}
9106+
9107+
assert(locator);
9108+
90849109
resultExpr = Rewriter.coerceToType(
9085-
resultExpr, solution.simplifyType(convertType),
9086-
cs.getConstraintLocator(resultExpr,
9087-
LocatorPathElt::ContextualType(
9088-
target.getExprContextualTypePurpose())));
9110+
resultExpr, solution.simplifyType(convertType), locator);
90899111
} else if (cs.getType(resultExpr)->hasLValueType() &&
90909112
!target.isDiscardedExpr()) {
90919113
// We referenced an lvalue. Load it.

lib/Sema/CSClosure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ class SyntacticElementSolutionApplication
16621662
assert(isSingleExpression);
16631663
resultTarget = SolutionApplicationTarget(
16641664
resultExpr, context.getAsDeclContext(),
1665-
mode == convertToResult ? CTP_ReturnStmt : CTP_Unused,
1665+
mode == convertToResult ? CTP_ClosureResult : CTP_Unused,
16661666
mode == convertToResult ? resultType : Type(),
16671667
/*isDiscarded=*/false);
16681668
}

0 commit comments

Comments
 (0)