Skip to content

Commit e801342

Browse files
committed
[CSClosure] Rename closure constraint generator and switch to AnyFunctionRef
Closure constraint generator has been renamed to `SyntacticElementGenerator` and can now handle both closure and function bodies.
1 parent 6a65810 commit e801342

File tree

1 file changed

+48
-36
lines changed

1 file changed

+48
-36
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -246,21 +246,22 @@ static ProtocolDecl *getSequenceProtocol(ASTContext &ctx, SourceLoc loc,
246246
}
247247

248248
/// Statement visitor that generates constraints for a given closure body.
249-
class ClosureConstraintGenerator
250-
: public StmtVisitor<ClosureConstraintGenerator, void> {
251-
friend StmtVisitor<ClosureConstraintGenerator, void>;
249+
class SyntacticElementConstraintGenerator
250+
: public StmtVisitor<SyntacticElementConstraintGenerator, void> {
251+
friend StmtVisitor<SyntacticElementConstraintGenerator, void>;
252252

253253
ConstraintSystem &cs;
254-
ClosureExpr *closure;
254+
AnyFunctionRef context;
255+
Type resultType;
255256
ConstraintLocator *locator;
256257

257258
public:
258259
/// Whether an error was encountered while generating constraints.
259260
bool hadError = false;
260261

261-
ClosureConstraintGenerator(ConstraintSystem &cs, ClosureExpr *closure,
262-
ConstraintLocator *locator)
263-
: cs(cs), closure(closure), locator(locator) {}
262+
SyntacticElementConstraintGenerator(ConstraintSystem &cs, AnyFunctionRef fn,
263+
Type resultTy, ConstraintLocator *locator)
264+
: cs(cs), context(fn), resultType(resultTy), locator(locator) {}
264265

265266
void visitPattern(Pattern *pattern, ContextualTypeInfo context) {
266267
auto parentElement =
@@ -286,13 +287,13 @@ class ClosureConstraintGenerator
286287
llvm_unreachable("Unsupported pattern");
287288
}
288289

289-
void visitCaseItem(CaseLabelItem *caseItem, ContextualTypeInfo context) {
290-
assert(context.purpose == CTP_CaseStmt);
290+
void visitCaseItem(CaseLabelItem *caseItem, ContextualTypeInfo contextInfo) {
291+
assert(contextInfo.purpose == CTP_CaseStmt);
291292

292293
// Resolve the pattern.
293294
auto *pattern = caseItem->getPattern();
294295
if (!caseItem->isPatternResolved()) {
295-
pattern = TypeChecker::resolvePattern(pattern, closure,
296+
pattern = TypeChecker::resolvePattern(pattern, context.getAsDeclContext(),
296297
/*isStmtCondition=*/false);
297298
if (!pattern) {
298299
hadError = true;
@@ -306,13 +307,13 @@ class ClosureConstraintGenerator
306307
// always be converted into a conjunction.
307308

308309
// Generate constraints for pattern.
309-
visitPattern(pattern, context);
310+
visitPattern(pattern, contextInfo);
310311

311312
auto *guardExpr = caseItem->getGuardExpr();
312313

313314
// Generate constraints for `where` clause (if any).
314315
if (guardExpr) {
315-
guardExpr = cs.generateConstraints(guardExpr, closure);
316+
guardExpr = cs.generateConstraints(guardExpr, context.getAsDeclContext());
316317
if (!guardExpr) {
317318
hadError = true;
318319
return;
@@ -341,7 +342,7 @@ class ClosureConstraintGenerator
341342
// Verify pattern.
342343
{
343344
auto contextualPattern =
344-
ContextualPattern::forRawPattern(pattern, closure);
345+
ContextualPattern::forRawPattern(pattern, context.getAsDeclContext());
345346
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);
346347

347348
if (patternType->hasError()) {
@@ -380,7 +381,7 @@ class ClosureConstraintGenerator
380381

381382
{
382383
SolutionApplicationTarget target(
383-
sequenceExpr, closure, CTP_ForEachSequence,
384+
sequenceExpr, context.getAsDeclContext(), CTP_ForEachSequence,
384385
sequenceProto->getDeclaredInterfaceType(),
385386
/*isDiscarded=*/false);
386387

@@ -426,14 +427,14 @@ class ClosureConstraintGenerator
426427
Type makeIteratorType =
427428
cs.createTypeVariable(locator, TVO_CanBindToNoEscape);
428429
cs.addValueWitnessConstraint(LValueType::get(sequenceType), makeIterator,
429-
makeIteratorType, closure,
430+
makeIteratorType, context.getAsDeclContext(),
430431
FunctionRefKind::Compound, contextualLocator);
431432

432433
// After successful constraint generation, let's record
433434
// solution application target with all relevant information.
434435
{
435436
auto target = SolutionApplicationTarget::forForEachStmt(
436-
forEachStmt, sequenceProto, closure,
437+
forEachStmt, sequenceProto, context.getAsDeclContext(),
437438
/*bindTypeVarsOneWay=*/false,
438439
/*contextualPurpose=*/CTP_ForEachSequence);
439440

@@ -761,9 +762,9 @@ class ClosureConstraintGenerator
761762
// be handled together with pattern because pattern can
762763
// inform a type of sequence element e.g. `for i: Int8 in 0 ..< 8`
763764
{
764-
Pattern *pattern =
765-
TypeChecker::resolvePattern(forEachStmt->getPattern(), closure,
766-
/*isStmtCondition=*/false);
765+
Pattern *pattern = TypeChecker::resolvePattern(forEachStmt->getPattern(),
766+
context.getAsDeclContext(),
767+
/*isStmtCondition=*/false);
767768

768769
if (!pattern) {
769770
hadError = true;
@@ -798,7 +799,8 @@ class ClosureConstraintGenerator
798799
{
799800
elements.push_back(makeElement(subjectExpr, switchLoc));
800801

801-
SolutionApplicationTarget target(subjectExpr, closure, CTP_Unused,
802+
SolutionApplicationTarget target(subjectExpr,
803+
context.getAsDeclContext(), CTP_Unused,
802804
Type(), /*isDiscarded=*/false);
803805

804806
cs.setSolutionApplicationTarget(switchStmt, target);
@@ -853,7 +855,7 @@ class ClosureConstraintGenerator
853855
}
854856
}
855857

856-
bindSwitchCasePatternVars(closure, caseStmt);
858+
bindSwitchCasePatternVars(context.getAsDeclContext(), caseStmt);
857859

858860
auto *caseLoc = cs.getConstraintLocator(
859861
locator, LocatorPathElt::SyntacticElement(caseStmt));
@@ -912,7 +914,7 @@ class ClosureConstraintGenerator
912914
for (auto node : braceStmt->getElements()) {
913915
if (auto expr = node.dyn_cast<Expr *>()) {
914916
auto generatedExpr = cs.generateConstraints(
915-
expr, closure, /*isInputExpression=*/false);
917+
expr, context.getAsDeclContext(), /*isInputExpression=*/false);
916918
if (!generatedExpr) {
917919
hadError = true;
918920
}
@@ -925,24 +927,27 @@ class ClosureConstraintGenerator
925927
}
926928

927929
void visitReturnStmt(ReturnStmt *returnStmt) {
928-
auto contextualTy = cs.getClosureType(closure)->getResult();
930+
auto *closure =
931+
dyn_cast_or_null<ClosureExpr>(context.getAbstractClosureExpr());
929932

930933
// Single-expression closures are effectively a `return` statement,
931934
// so let's give them a special locator as to indicate that.
932935
// Return statements might not have a result if we have a closure whose
933936
// implicit returned value is coerced to Void.
934-
if (closure->hasSingleExpressionBody() && returnStmt->hasResult()) {
937+
if (closure && closure->hasSingleExpressionBody() &&
938+
returnStmt->hasResult()) {
935939
auto *expr = returnStmt->getResult();
936940
assert(expr && "single expression closure without expression?");
937941

938-
expr = cs.generateConstraints(expr, closure, /*isInputExpression=*/false);
942+
expr = cs.generateConstraints(expr, closure,
943+
/*isInputExpression=*/false);
939944
if (!expr) {
940945
hadError = true;
941946
return;
942947
}
943948

944949
cs.addConstraint(
945-
ConstraintKind::Conversion, cs.getType(expr), contextualTy,
950+
ConstraintKind::Conversion, cs.getType(expr), resultType,
946951
cs.getConstraintLocator(
947952
closure, LocatorPathElt::ClosureBody(
948953
/*hasReturn=*/!returnStmt->isImplicit())));
@@ -957,26 +962,30 @@ class ClosureConstraintGenerator
957962
} else {
958963
// If this is simplify `return`, let's create an empty tuple
959964
// which is also useful if contextual turns out to be e.g. `Void?`.
960-
resultExpr = getVoidExpr(closure->getASTContext());
965+
resultExpr = getVoidExpr(cs.getASTContext());
961966
}
962967

963-
SolutionApplicationTarget target(resultExpr, closure, CTP_ReturnStmt,
964-
contextualTy,
968+
SolutionApplicationTarget target(resultExpr, context.getAsDeclContext(),
969+
CTP_ReturnStmt, resultType,
965970
/*isDiscarded=*/false);
966971

967972
if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
968973
hadError = true;
969974
return;
970975
}
971976

972-
cs.setContextualType(target.getAsExpr(), TypeLoc::withoutLoc(contextualTy),
977+
cs.setContextualType(target.getAsExpr(), TypeLoc::withoutLoc(resultType),
973978
CTP_ReturnStmt);
974979
cs.setSolutionApplicationTarget(returnStmt, target);
975980
}
976981

977982
bool isSupportedMultiStatementClosure() const {
978-
return !closure->hasSingleExpressionBody() &&
979-
cs.participatesInInference(closure);
983+
if (auto *closure =
984+
dyn_cast_or_null<ClosureExpr>(context.getAbstractClosureExpr())) {
985+
return !closure->hasSingleExpressionBody() &&
986+
cs.participatesInInference(closure);
987+
}
988+
return true;
980989
}
981990

982991
#define UNSUPPORTED_STMT(STMT) void visit##STMT##Stmt(STMT##Stmt *) { \
@@ -1008,8 +1017,10 @@ bool ConstraintSystem::generateConstraints(ClosureExpr *closure) {
10081017
auto &ctx = closure->getASTContext();
10091018

10101019
if (participatesInInference(closure)) {
1011-
ClosureConstraintGenerator generator(*this, closure,
1012-
getConstraintLocator(closure));
1020+
SyntacticElementConstraintGenerator generator(
1021+
*this, closure, getClosureType(closure)->getResult(),
1022+
getConstraintLocator(closure));
1023+
10131024
generator.visit(closure->getBody());
10141025

10151026
if (closure->hasSingleExpressionBody())
@@ -1079,8 +1090,9 @@ ConstraintSystem::simplifySyntacticElementConstraint(
10791090
TypeMatchOptions flags, ConstraintLocatorBuilder locator) {
10801091
auto *closure = castToExpr<ClosureExpr>(locator.getAnchor());
10811092

1082-
ClosureConstraintGenerator generator(*this, closure,
1083-
getConstraintLocator(locator));
1093+
SyntacticElementConstraintGenerator generator(
1094+
*this, closure, getClosureType(closure)->getResult(),
1095+
getConstraintLocator(locator));
10841096

10851097
if (auto *expr = element.dyn_cast<Expr *>()) {
10861098
SolutionApplicationTarget target(expr, closure, context.purpose,

0 commit comments

Comments
 (0)