Skip to content

Commit 3a44e7d

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 b6ded0d commit 3a44e7d

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
@@ -3646,6 +3646,14 @@ class ConstraintSystem {
36463646
return known->second;
36473647
}
36483648

3649+
Optional<AppliedBuilderTransform>
3650+
getAppliedResultBuilderTransform(AnyFunctionRef fn) const {
3651+
auto transformed = resultBuilderTransformed.find(fn);
3652+
if (transformed != resultBuilderTransformed.end())
3653+
return transformed->second;
3654+
return None;
3655+
}
3656+
36493657
void setCaseLabelItemInfo(const CaseLabelItem *item, CaseLabelItemInfo info) {
36503658
assert(item != nullptr);
36513659
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

@@ -921,14 +918,40 @@ class SyntacticElementConstraintGenerator
921918
return;
922919
}
923920

924-
cs.setContextualType(target.getAsExpr(), TypeLoc::withoutLoc(resultType),
921+
cs.setContextualType(target.getAsExpr(),
922+
TypeLoc::withoutLoc(getContextualResultType()),
925923
CTP_ReturnStmt);
926924
cs.setSolutionApplicationTarget(returnStmt, target);
927925
}
928926

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

0 commit comments

Comments
 (0)