Skip to content

Commit 96e6952

Browse files
committed
[CSClosure] Teach syntactic element constraint generator about result builders
Closures and functions that have result builder transform applied have to be handled specially by the constraint generator because transformed body is associated with the context (function or closure) only during solution application.
1 parent 432ce1c commit 96e6952

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3734,6 +3734,14 @@ class ConstraintSystem {
37343734
return known->second;
37353735
}
37363736

3737+
Optional<AppliedBuilderTransform>
3738+
getAppliedResultBuilderTransform(AnyFunctionRef fn) const {
3739+
auto transformed = resultBuilderTransformed.find(fn);
3740+
if (transformed != resultBuilderTransformed.end())
3741+
return transformed->second;
3742+
return None;
3743+
}
3744+
37373745
void setCaseLabelItemInfo(const CaseLabelItem *item, CaseLabelItemInfo info) {
37383746
assert(item != nullptr);
37393747
assert(caseLabelItems.count(item) == 0);

lib/Sema/CSClosure.cpp

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -874,30 +874,27 @@ class SyntacticElementConstraintGenerator
874874
}
875875

876876
void visitReturnStmt(ReturnStmt *returnStmt) {
877-
auto *closure =
878-
dyn_cast_or_null<ClosureExpr>(context.getAbstractClosureExpr());
879-
880877
// Single-expression closures are effectively a `return` statement,
881878
// so let's give them a special locator as to indicate that.
882879
// Return statements might not have a result if we have a closure whose
883880
// implicit returned value is coerced to Void.
884-
if (closure && closure->hasSingleExpressionBody() &&
885-
returnStmt->hasResult()) {
881+
if (isInSingleExpressionClosure() && returnStmt->hasResult()) {
886882
auto *expr = returnStmt->getResult();
887883
assert(expr && "single expression closure without expression?");
888884

889-
expr = cs.generateConstraints(expr, closure,
885+
expr = cs.generateConstraints(expr, context.getAsDeclContext(),
890886
/*isInputExpression=*/false);
891887
if (!expr) {
892888
hadError = true;
893889
return;
894890
}
895891

896-
cs.addConstraint(
897-
ConstraintKind::Conversion, cs.getType(expr), resultType,
898-
cs.getConstraintLocator(
899-
closure, LocatorPathElt::ClosureBody(
900-
/*hasReturn=*/!returnStmt->isImplicit())));
892+
cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
893+
getContextualResultType(),
894+
cs.getConstraintLocator(
895+
context.getAbstractClosureExpr(),
896+
LocatorPathElt::ClosureBody(
897+
/*hasReturn=*/!returnStmt->isImplicit())));
901898
return;
902899
}
903900

@@ -923,14 +920,40 @@ class SyntacticElementConstraintGenerator
923920
return;
924921
}
925922

926-
cs.setContextualType(target.getAsExpr(), TypeLoc::withoutLoc(resultType),
923+
cs.setContextualType(target.getAsExpr(),
924+
TypeLoc::withoutLoc(getContextualResultType()),
927925
CTP_ReturnStmt);
928926
cs.setSolutionApplicationTarget(returnStmt, target);
929927
}
930928

929+
bool isInSingleExpressionClosure() {
930+
if (!isExpr<ClosureExpr>(context.getAbstractClosureExpr()))
931+
return false;
932+
933+
// Result builder transformed bodies are never single-expression.
934+
if (cs.getAppliedResultBuilderTransform(context))
935+
return false;
936+
937+
return context.hasSingleExpressionBody();
938+
}
939+
940+
Type getContextualResultType() const {
941+
if (auto transform = cs.getAppliedResultBuilderTransform(context))
942+
return transform->bodyResultType;
943+
944+
if (auto *closure =
945+
getAsExpr<ClosureExpr>(context.getAbstractClosureExpr()))
946+
return cs.getClosureType(closure)->getResult();
947+
948+
return context.getBodyResultType();
949+
}
950+
931951
bool isSupportedMultiStatementClosure() const {
952+
if (cs.getAppliedResultBuilderTransform(context))
953+
return true;
954+
932955
if (auto *closure =
933-
dyn_cast_or_null<ClosureExpr>(context.getAbstractClosureExpr())) {
956+
getAsExpr<ClosureExpr>(context.getAbstractClosureExpr())) {
934957
return !closure->hasSingleExpressionBody() &&
935958
cs.participatesInInference(closure);
936959
}

0 commit comments

Comments
 (0)