Skip to content

Commit af048d6

Browse files
committed
[Constraint system] Move solution application for closures to CSClosure.
Slim down CSApply.cpp by moving the logic for applying a solution to a closure into CSClosure.cpp. Also, eliminate duplicated logic for applying function builders to the body of a closure or function. This should not change semantics at all.
1 parent b9b8f08 commit af048d6

File tree

4 files changed

+291
-203
lines changed

4 files changed

+291
-203
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ class AnyFunctionRef {
8989
return TheFunction.get<AbstractClosureExpr *>()->getSingleExpressionBody();
9090
}
9191

92+
void setSingleExpressionBody(Expr *expr) {
93+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
94+
AFD->setSingleExpressionBody(expr);
95+
return;
96+
}
97+
98+
auto ACE = TheFunction.get<AbstractClosureExpr *>();
99+
if (auto CE = dyn_cast<ClosureExpr>(ACE)) {
100+
CE->setSingleExpressionBody(expr);
101+
} else {
102+
cast<AutoClosureExpr>(ACE)->setBody(expr);
103+
}
104+
}
105+
92106
Type getType() const {
93107
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
94108
return AFD->getInterfaceType();
@@ -123,6 +137,21 @@ class AnyFunctionRef {
123137
return cast<AutoClosureExpr>(ACE)->getBody();
124138
}
125139

140+
void setBody(BraceStmt *stmt, bool isSingleExpression) {
141+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
142+
AFD->setBody(stmt);
143+
AFD->setHasSingleExpressionBody(isSingleExpression);
144+
return;
145+
}
146+
147+
auto *ACE = TheFunction.get<AbstractClosureExpr *>();
148+
if (auto *CE = dyn_cast<ClosureExpr>(ACE)) {
149+
return CE->setBody(stmt, isSingleExpression);
150+
}
151+
152+
llvm_unreachable("autoclosures don't have statement bodies");
153+
}
154+
126155
DeclContext *getAsDeclContext() const {
127156
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
128157
return AFD;

lib/Sema/CSApply.cpp

Lines changed: 34 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,30 +1504,6 @@ namespace {
15041504
}
15051505

15061506
public:
1507-
1508-
1509-
/// Coerce a closure expression with a non-Void return type to a
1510-
/// contextual function type with a Void return type.
1511-
///
1512-
/// This operation cannot fail.
1513-
///
1514-
/// \param expr The closure expression to coerce.
1515-
///
1516-
/// \returns The coerced closure expression.
1517-
///
1518-
ClosureExpr *coerceClosureExprToVoid(ClosureExpr *expr);
1519-
1520-
/// Coerce a closure expression with a Never return type to a
1521-
/// contextual function type with some other return type.
1522-
///
1523-
/// This operation cannot fail.
1524-
///
1525-
/// \param expr The closure expression to coerce.
1526-
///
1527-
/// \returns The coerced closure expression.
1528-
///
1529-
ClosureExpr *coerceClosureExprFromNever(ClosureExpr *expr);
1530-
15311507
/// Coerce the given expression to the given type.
15321508
///
15331509
/// This operation cannot fail.
@@ -4994,14 +4970,6 @@ namespace {
49944970
return result;
49954971
}
49964972

4997-
const AppliedBuilderTransform *getAppliedBuilderTransform(
4998-
AnyFunctionRef fn) {
4999-
auto known = solution.functionBuilderTransformed.find(fn);
5000-
return known != solution.functionBuilderTransformed.end()
5001-
? &known->second
5002-
: nullptr;
5003-
}
5004-
50054973
void finalize() {
50064974
assert(ExprStack.empty());
50074975
assert(OpenedExistentials.empty());
@@ -5831,83 +5799,6 @@ static bool applyTypeToClosureExpr(ConstraintSystem &cs,
58315799
return false;
58325800
}
58335801

5834-
ClosureExpr *ExprRewriter::coerceClosureExprToVoid(ClosureExpr *closureExpr) {
5835-
auto &ctx = cs.getASTContext();
5836-
5837-
// Re-write the single-expression closure to return '()'
5838-
assert(closureExpr->hasSingleExpressionBody());
5839-
5840-
// A single-expression body contains a single return statement
5841-
// prior to this transformation.
5842-
auto member = closureExpr->getBody()->getFirstElement();
5843-
5844-
if (member.is<Stmt *>()) {
5845-
auto returnStmt = cast<ReturnStmt>(member.get<Stmt *>());
5846-
auto singleExpr = returnStmt->getResult();
5847-
auto voidExpr = cs.cacheType(TupleExpr::createEmpty(
5848-
ctx, singleExpr->getStartLoc(), singleExpr->getEndLoc(),
5849-
/*implicit*/ true));
5850-
returnStmt->setResult(voidExpr);
5851-
5852-
// For l-value types, reset to the object type. This might not be strictly
5853-
// necessary any more, but it's probably still a good idea.
5854-
if (cs.getType(singleExpr)->is<LValueType>())
5855-
cs.setType(singleExpr,
5856-
cs.getType(singleExpr)->getWithoutSpecifierType());
5857-
5858-
solution.setExprTypes(singleExpr);
5859-
TypeChecker::checkIgnoredExpr(singleExpr);
5860-
5861-
SmallVector<ASTNode, 2> elements;
5862-
elements.push_back(singleExpr);
5863-
elements.push_back(returnStmt);
5864-
5865-
auto braceStmt = BraceStmt::create(ctx, closureExpr->getStartLoc(),
5866-
elements, closureExpr->getEndLoc(),
5867-
/*implicit*/ true);
5868-
5869-
closureExpr->setImplicit();
5870-
closureExpr->setBody(braceStmt, /*isSingleExpression*/true);
5871-
}
5872-
5873-
// Finally, compute the proper type for the closure.
5874-
auto fnType = cs.getType(closureExpr)->getAs<FunctionType>();
5875-
auto newClosureType = FunctionType::get(
5876-
fnType->getParams(), ctx.TheEmptyTupleType, fnType->getExtInfo());
5877-
cs.setType(closureExpr, newClosureType);
5878-
return closureExpr;
5879-
}
5880-
5881-
ClosureExpr *ExprRewriter::coerceClosureExprFromNever(ClosureExpr *closureExpr) {
5882-
// Re-write the single-expression closure to drop the 'return'.
5883-
assert(closureExpr->hasSingleExpressionBody());
5884-
5885-
// A single-expression body contains a single return statement
5886-
// prior to this transformation.
5887-
auto member = closureExpr->getBody()->getFirstElement();
5888-
5889-
if (member.is<Stmt *>()) {
5890-
auto returnStmt = cast<ReturnStmt>(member.get<Stmt *>());
5891-
auto singleExpr = returnStmt->getResult();
5892-
5893-
solution.setExprTypes(singleExpr);
5894-
TypeChecker::checkIgnoredExpr(singleExpr);
5895-
5896-
SmallVector<ASTNode, 1> elements;
5897-
elements.push_back(singleExpr);
5898-
5899-
auto braceStmt =
5900-
BraceStmt::create(cs.getASTContext(), closureExpr->getStartLoc(),
5901-
elements, closureExpr->getEndLoc(),
5902-
/*implicit*/ true);
5903-
5904-
closureExpr->setImplicit();
5905-
closureExpr->setBody(braceStmt, /*isSingleExpression*/true);
5906-
}
5907-
5908-
return closureExpr;
5909-
}
5910-
59115802
// Look through sugar and DotSyntaxBaseIgnoredExprs.
59125803
static Expr *
59135804
getSemanticExprForDeclOrMemberRef(Expr *expr) {
@@ -7721,80 +7612,7 @@ namespace {
77217612
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
77227613
// For closures, update the parameter types and check the body.
77237614
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
7724-
Rewriter.simplifyExprType(expr);
7725-
auto &cs = Rewriter.getConstraintSystem();
7726-
7727-
// Coerce the pattern, in case we resolved something.
7728-
auto fnType = cs.getType(closure)->castTo<FunctionType>();
7729-
auto *params = closure->getParameters();
7730-
TypeChecker::coerceParameterListToType(params, closure, fnType);
7731-
7732-
if (closure->hasExplicitResultType()) {
7733-
closure->setExplicitResultType(fnType->getResult());
7734-
}
7735-
7736-
if (auto transform =
7737-
Rewriter.getAppliedBuilderTransform(closure)) {
7738-
// Apply the function builder to the closure. We want to be in the
7739-
// context of the closure for subsequent transforms.
7740-
llvm::SaveAndRestore<DeclContext *> savedDC(Rewriter.dc, closure);
7741-
auto newBody = applyFunctionBuilderTransform(
7742-
Rewriter.solution, *transform, closure->getBody(), closure,
7743-
[&](SolutionApplicationTarget target) {
7744-
auto resultTarget = rewriteTarget(target);
7745-
if (resultTarget) {
7746-
if (auto expr = resultTarget->getAsExpr())
7747-
Rewriter.solution.setExprTypes(expr);
7748-
}
7749-
7750-
return resultTarget;
7751-
});
7752-
closure->setBody(newBody, /*isSingleExpression=*/false);
7753-
closure->setAppliedFunctionBuilder();
7754-
7755-
Rewriter.solution.setExprTypes(closure);
7756-
} else if (closure->hasSingleExpressionBody()) {
7757-
// If this is a single-expression closure, convert the expression
7758-
// in the body to the result type of the closure.
7759-
7760-
// Enter the context of the closure when type-checking the body.
7761-
llvm::SaveAndRestore<DeclContext *> savedDC(Rewriter.dc, closure);
7762-
Expr *body = closure->getSingleExpressionBody()->walk(*this);
7763-
if (!body)
7764-
return { false, nullptr };
7765-
7766-
if (body != closure->getSingleExpressionBody())
7767-
closure->setSingleExpressionBody(body);
7768-
7769-
if (body) {
7770-
// A single-expression closure with a non-Void expression type
7771-
// coerces to a Void-returning function type.
7772-
if (fnType->getResult()->isVoid() && !cs.getType(body)->isVoid()) {
7773-
closure = Rewriter.coerceClosureExprToVoid(closure);
7774-
// A single-expression closure with a Never expression type
7775-
// coerces to any other function type.
7776-
} else if (cs.getType(body)->isUninhabited()) {
7777-
closure = Rewriter.coerceClosureExprFromNever(closure);
7778-
} else {
7779-
7780-
body = Rewriter.coerceToType(body,
7781-
fnType->getResult(),
7782-
cs.getConstraintLocator(
7783-
closure,
7784-
ConstraintLocator::ClosureResult));
7785-
if (!body)
7786-
return { false, nullptr };
7787-
7788-
closure->setSingleExpressionBody(body);
7789-
}
7790-
}
7791-
} else {
7792-
// For other closures, type-check the body once we've finished with
7793-
// the expression.
7794-
Rewriter.solution.setExprTypes(closure);
7795-
ClosuresToTypeCheck.push_back(closure);
7796-
}
7797-
7615+
rewriteFunction(closure);
77987616
return { false, closure };
77997617
}
78007618

@@ -7823,6 +7641,37 @@ namespace {
78237641
/// Rewrite the target, producing a new target.
78247642
Optional<SolutionApplicationTarget>
78257643
rewriteTarget(SolutionApplicationTarget target);
7644+
7645+
/// Rewrite the function for the given solution.
7646+
///
7647+
/// \returns true if an error occurred.
7648+
bool rewriteFunction(AnyFunctionRef fn) {
7649+
auto result = Rewriter.cs.applySolution(
7650+
Rewriter.solution, fn, Rewriter.dc,
7651+
[&](SolutionApplicationTarget target) {
7652+
auto resultTarget = rewriteTarget(target);
7653+
if (resultTarget) {
7654+
if (auto expr = resultTarget->getAsExpr())
7655+
Rewriter.solution.setExprTypes(expr);
7656+
}
7657+
7658+
return resultTarget;
7659+
});
7660+
7661+
switch (result) {
7662+
case SolutionApplicationToFunctionResult::Success:
7663+
return false;
7664+
7665+
case SolutionApplicationToFunctionResult::Failure:
7666+
return true;
7667+
7668+
case SolutionApplicationToFunctionResult::Delay: {
7669+
auto closure = cast<ClosureExpr>(fn.getAbstractClosureExpr());
7670+
ClosuresToTypeCheck.push_back(closure);
7671+
return false;
7672+
}
7673+
}
7674+
}
78267675
};
78277676
} // end anonymous namespace
78287677

@@ -8256,28 +8105,10 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
82568105
return target;
82578106
} else {
82588107
auto fn = *target.getAsFunction();
8259-
8260-
// Dig out the function builder transformation we applied.
8261-
auto transform = Rewriter.getAppliedBuilderTransform(fn);
8262-
assert(transform);
8263-
8264-
auto newBody = applyFunctionBuilderTransform(
8265-
solution, *transform, fn.getBody(), fn.getAsDeclContext(),
8266-
[&](SolutionApplicationTarget target) {
8267-
auto resultTarget = rewriteTarget(target);
8268-
if (resultTarget) {
8269-
if (auto expr = resultTarget->getAsExpr())
8270-
solution.setExprTypes(expr);
8271-
}
8272-
8273-
return resultTarget;
8274-
});
8275-
8276-
if (!newBody)
8108+
if (rewriteFunction(fn))
82778109
return None;
82788110

8279-
result.setFunctionBody(newBody);
8280-
fn.getAbstractFunctionDecl()->setHasSingleExpressionBody(false);
8111+
result.setFunctionBody(fn.getBody());
82818112
}
82828113

82838114
// Follow-up tasks.

0 commit comments

Comments
 (0)