Skip to content

Commit 3981a68

Browse files
authored
Merge pull request #29626 from DougGregor/function-builders-single-expr-closures-return
[Constraint solver] Fix function builders with single-expression closures
2 parents 7e11809 + f8eee50 commit 3981a68

File tree

5 files changed

+40
-23
lines changed

5 files changed

+40
-23
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,15 @@ class BuilderClosureVisitor
244244
expressions.push_back(buildVarRef(childVar, childVar->getLoc()));
245245
};
246246

247-
for (const auto &node : braceStmt->getElements()) {
247+
for (auto node : braceStmt->getElements()) {
248+
// Implicit returns in single-expression function bodies are treated
249+
// as the expression.
250+
if (auto returnStmt =
251+
dyn_cast_or_null<ReturnStmt>(node.dyn_cast<Stmt *>())) {
252+
assert(returnStmt->isImplicit());
253+
node = returnStmt->getResult();
254+
}
255+
248256
if (auto stmt = node.dyn_cast<Stmt *>()) {
249257
addChild(visit(stmt));
250258
continue;
@@ -291,14 +299,9 @@ class BuilderClosureVisitor
291299
}
292300

293301
VarDecl *visitReturnStmt(ReturnStmt *stmt) {
294-
// Allow implicit returns due to 'return' elision.
295-
if (!stmt->isImplicit() || !stmt->hasResult()) {
296-
if (!unhandledNode)
297-
unhandledNode = stmt;
298-
return nullptr;
299-
}
300-
301-
return captureExpr(stmt->getResult(), /*oneWay=*/true);
302+
if (!unhandledNode)
303+
unhandledNode = stmt;
304+
return nullptr;
302305
}
303306

304307
VarDecl *visitDoStmt(DoStmt *doStmt) {
@@ -1116,7 +1119,8 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
11161119
return nullptr;
11171120
}
11181121

1119-
ConstraintSystem::TypeMatchResult ConstraintSystem::matchFunctionBuilder(
1122+
Optional<ConstraintSystem::TypeMatchResult>
1123+
ConstraintSystem::matchFunctionBuilder(
11201124
AnyFunctionRef fn, Type builderType, Type bodyResultType,
11211125
ConstraintKind bodyResultConstraintKind,
11221126
ConstraintLocator *calleeLocator, ConstraintLocatorBuilder locator) {
@@ -1140,7 +1144,7 @@ ConstraintSystem::TypeMatchResult ConstraintSystem::matchFunctionBuilder(
11401144
case FunctionBuilderBodyPreCheck::HasReturnStmt:
11411145
// If the body has a return statement, suppress the transform but
11421146
// continue solving the constraint system.
1143-
return getTypeMatchSuccess();
1147+
return None;
11441148
}
11451149

11461150
// Check the form of this body to see if we can apply the
@@ -1286,12 +1290,6 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
12861290
llvm::Expected<FunctionBuilderBodyPreCheck>
12871291
PreCheckFunctionBuilderRequest::evaluate(Evaluator &eval,
12881292
AnyFunctionRef fn) const {
1289-
// Single-expression closures should already have been pre-checked.
1290-
if (auto closure = fn.getAbstractClosureExpr()) {
1291-
if (closure->hasSingleExpressionBody())
1292-
return FunctionBuilderBodyPreCheck::Okay;
1293-
}
1294-
12951293
return PreCheckFunctionBuilderApplication(fn, false).run();
12961294
}
12971295

lib/Sema/CSSimplify.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6635,10 +6635,11 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
66356635
auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator));
66366636
if (auto functionBuilderType = getFunctionBuilderTypeFor(
66376637
*this, argToParam->getParamIdx(), calleeLocator)) {
6638-
auto result = matchFunctionBuilder(
6639-
closure, functionBuilderType, closureType->getResult(),
6640-
ConstraintKind::Conversion, calleeLocator, locator);
6641-
return result.isSuccess();
6638+
if (auto result = matchFunctionBuilder(
6639+
closure, functionBuilderType, closureType->getResult(),
6640+
ConstraintKind::Conversion, calleeLocator, locator)) {
6641+
return result->isSuccess();
6642+
}
66426643
}
66436644
}
66446645
}

lib/Sema/ConstraintGraph.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ namespace {
942942
for (auto lhsTypeRep : lhsTypeReps) {
943943
for (auto rhsTypeRep : rhsTypeReps) {
944944
if (lhsTypeRep == rhsTypeRep)
945-
break;
945+
continue;
946946

947947
insertIfUnique(oneWayDigraph[rhsTypeRep].outAdjacencies,lhsTypeRep);
948948
insertIfUnique(oneWayDigraph[lhsTypeRep].inAdjacencies,rhsTypeRep);

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3767,7 +3767,10 @@ class ConstraintSystem {
37673767
void simplifyDisjunctionChoice(Constraint *choice);
37683768

37693769
/// Apply the given function builder to the closure expression.
3770-
TypeMatchResult matchFunctionBuilder(
3770+
///
3771+
/// \returns \c None when the function builder cannot be applied at all,
3772+
/// otherwise the result of applying the function builder.
3773+
Optional<TypeMatchResult> matchFunctionBuilder(
37713774
AnyFunctionRef fn, Type builderType, Type bodyResultType,
37723775
ConstraintKind bodyResultConstraintKind,
37733776
ConstraintLocator *calleeLocator, ConstraintLocatorBuilder locator);

test/Constraints/function_builder_diags.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,18 @@ func checkConditions(cond: Bool) {
284284
}
285285
}
286286
}
287+
288+
// Check that a closure with a single "return" works with function builders.
289+
func checkSingleReturn(cond: Bool) {
290+
tuplify(cond) { value in
291+
return (value, 17)
292+
}
293+
294+
tuplify(cond) { value in
295+
(value, 17)
296+
}
297+
298+
tuplify(cond) {
299+
($0, 17)
300+
}
301+
}

0 commit comments

Comments
 (0)