Skip to content

Commit f1febc2

Browse files
committed
[Constraint system] Lift PatternBindingDecl into SolutionApplicationTarget.
Generalize the code used to generate constraints and apply solutions to PatternBindingDecls so that it is handled directly by the constaint system and solution, respectively, rather than as part of the function builder transform. No functionality change, but this is a cleaner abstraction.
1 parent b149341 commit f1febc2

File tree

4 files changed

+106
-20
lines changed

4 files changed

+106
-20
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -269,26 +269,12 @@ class BuilderClosureVisitor
269269
return;
270270
}
271271

272-
// If we aren't generating constraints, there's nothing to do.
273-
if (!cs)
274-
return;
275-
276-
/// Generate constraints for each pattern binding entry
277-
for (unsigned index : range(patternBinding->getNumPatternEntries())) {
278-
// Type check the pattern.
279-
auto pattern = patternBinding->getPattern(index);
280-
auto contextualPattern = ContextualPattern::forRawPattern(pattern, dc);
281-
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);
282-
283-
// Generate constraints for the initialization.
284-
auto target = SolutionApplicationTarget::forInitialization(
285-
patternBinding->getInit(index), dc, patternType, pattern,
286-
/*bindPatternVarsOneWay=*/true);
272+
// If there is a constraint system, generate constraints for the pattern
273+
// binding.
274+
if (cs) {
275+
SolutionApplicationTarget target(patternBinding);
287276
if (cs->generateConstraints(target, FreeTypeVariableBinding::Disallow))
288-
continue;
289-
290-
// Keep track of this binding entry.
291-
cs->setSolutionApplicationTarget({patternBinding, index}, target);
277+
hadError = true;
292278
}
293279
}
294280

lib/Sema/CSApply.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8103,6 +8103,25 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
81038103
solution.setExprTypes(guardExpr);
81048104
}
81058105

8106+
return target;
8107+
} else if (auto patternBinding = target.getAsPatternBinding()) {
8108+
ConstraintSystem &cs = solution.getConstraintSystem();
8109+
for (unsigned index : range(patternBinding->getNumPatternEntries())) {
8110+
// Find the solution application target for this.
8111+
auto knownTarget = *cs.getSolutionApplicationTarget(
8112+
{patternBinding, index});
8113+
8114+
// Rewrite the target.
8115+
auto resultTarget = rewriteTarget(knownTarget);
8116+
if (!resultTarget)
8117+
return None;
8118+
8119+
patternBinding->setPattern(
8120+
index, resultTarget->getInitializationPattern(),
8121+
resultTarget->getDeclContext());
8122+
patternBinding->setInit(index, resultTarget->getAsExpr());
8123+
}
8124+
81068125
return target;
81078126
} else {
81088127
auto fn = *target.getAsFunction();
@@ -8380,6 +8399,10 @@ SolutionApplicationTarget SolutionApplicationTarget::walk(ASTWalker &walker) {
83808399
}
83818400

83828401
return *this;
8402+
8403+
case Kind::patternBinding:
8404+
return *this;
83838405
}
8406+
83848407
llvm_unreachable("invalid target kind");
83858408
}

lib/Sema/CSGen.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4428,7 +4428,48 @@ bool ConstraintSystem::generateConstraints(
44284428
return false;
44294429
}
44304430

4431-
llvm_unreachable("BOOM");
4431+
switch (target.kind) {
4432+
case SolutionApplicationTarget::Kind::expression:
4433+
llvm_unreachable("Handled above");
4434+
4435+
case SolutionApplicationTarget::Kind::caseLabelItem:
4436+
case SolutionApplicationTarget::Kind::function:
4437+
case SolutionApplicationTarget::Kind::stmtCondition:
4438+
llvm_unreachable("Handled separately");
4439+
4440+
case SolutionApplicationTarget::Kind::patternBinding: {
4441+
auto patternBinding = target.getAsPatternBinding();
4442+
auto dc = target.getDeclContext();
4443+
bool hadError = false;
4444+
4445+
/// Generate constraints for each pattern binding entry
4446+
for (unsigned index : range(patternBinding->getNumPatternEntries())) {
4447+
// Type check the pattern.
4448+
auto pattern = patternBinding->getPattern(index);
4449+
auto contextualPattern = ContextualPattern::forRawPattern(pattern, dc);
4450+
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);
4451+
4452+
auto init = patternBinding->getInit(index);
4453+
if (!init) {
4454+
llvm_unreachable("Unsupported pattern binding entry");
4455+
}
4456+
4457+
// Generate constraints for the initialization.
4458+
auto target = SolutionApplicationTarget::forInitialization(
4459+
init, dc, patternType, pattern,
4460+
/*bindPatternVarsOneWay=*/true);
4461+
if (generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
4462+
hadError = true;
4463+
continue;
4464+
}
4465+
4466+
// Keep track of this binding entry.
4467+
setSolutionApplicationTarget({patternBinding, index}, target);
4468+
}
4469+
4470+
return hadError;
4471+
}
4472+
}
44324473
}
44334474

44344475
Expr *ConstraintSystem::generateConstraints(

lib/Sema/ConstraintSystem.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,13 +1334,16 @@ struct DynamicCallableMethods {
13341334
/// Describes the target to which a constraint system's solution can be
13351335
/// applied.
13361336
class SolutionApplicationTarget {
1337+
public:
13371338
enum class Kind {
13381339
expression,
13391340
function,
13401341
stmtCondition,
13411342
caseLabelItem,
1343+
patternBinding,
13421344
} kind;
13431345

1346+
private:
13441347
union {
13451348
struct {
13461349
/// The expression being type-checked.
@@ -1402,6 +1405,8 @@ class SolutionApplicationTarget {
14021405
CaseLabelItem *caseLabelItem;
14031406
DeclContext *dc;
14041407
} caseLabelItem;
1408+
1409+
PatternBindingDecl *patternBinding;
14051410
};
14061411

14071412
// If the pattern contains a single variable that has an attached
@@ -1442,6 +1447,11 @@ class SolutionApplicationTarget {
14421447
this->caseLabelItem.dc = dc;
14431448
}
14441449

1450+
SolutionApplicationTarget(PatternBindingDecl *patternBinding) {
1451+
kind = Kind::patternBinding;
1452+
this->patternBinding = patternBinding;
1453+
}
1454+
14451455
/// Form a target for the initialization of a pattern from an expression.
14461456
static SolutionApplicationTarget forInitialization(
14471457
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern,
@@ -1467,6 +1477,7 @@ class SolutionApplicationTarget {
14671477
case Kind::function:
14681478
case Kind::stmtCondition:
14691479
case Kind::caseLabelItem:
1480+
case Kind::patternBinding:
14701481
return nullptr;
14711482
}
14721483
llvm_unreachable("invalid expression type");
@@ -1485,6 +1496,9 @@ class SolutionApplicationTarget {
14851496

14861497
case Kind::caseLabelItem:
14871498
return caseLabelItem.dc;
1499+
1500+
case Kind::patternBinding:
1501+
return patternBinding->getDeclContext();
14881502
}
14891503
llvm_unreachable("invalid decl context type");
14901504
}
@@ -1636,6 +1650,7 @@ class SolutionApplicationTarget {
16361650
case Kind::expression:
16371651
case Kind::stmtCondition:
16381652
case Kind::caseLabelItem:
1653+
case Kind::patternBinding:
16391654
return None;
16401655

16411656
case Kind::function:
@@ -1649,6 +1664,7 @@ class SolutionApplicationTarget {
16491664
case Kind::expression:
16501665
case Kind::function:
16511666
case Kind::caseLabelItem:
1667+
case Kind::patternBinding:
16521668
return None;
16531669

16541670
case Kind::stmtCondition:
@@ -1662,6 +1678,7 @@ class SolutionApplicationTarget {
16621678
case Kind::expression:
16631679
case Kind::function:
16641680
case Kind::stmtCondition:
1681+
case Kind::patternBinding:
16651682
return None;
16661683

16671684
case Kind::caseLabelItem:
@@ -1670,6 +1687,19 @@ class SolutionApplicationTarget {
16701687
llvm_unreachable("invalid case label type");
16711688
}
16721689

1690+
PatternBindingDecl *getAsPatternBinding() const {
1691+
switch (kind) {
1692+
case Kind::expression:
1693+
case Kind::function:
1694+
case Kind::stmtCondition:
1695+
case Kind::caseLabelItem:
1696+
return nullptr;
1697+
1698+
case Kind::patternBinding:
1699+
return patternBinding;
1700+
}
1701+
}
1702+
16731703
BraceStmt *getFunctionBody() const {
16741704
assert(kind == Kind::function);
16751705
return function.body;
@@ -1695,6 +1725,9 @@ class SolutionApplicationTarget {
16951725

16961726
case Kind::caseLabelItem:
16971727
return caseLabelItem.caseLabelItem->getSourceRange();
1728+
1729+
case Kind::patternBinding:
1730+
return patternBinding->getSourceRange();
16981731
}
16991732
llvm_unreachable("invalid target type");
17001733
}
@@ -1713,6 +1746,9 @@ class SolutionApplicationTarget {
17131746

17141747
case Kind::caseLabelItem:
17151748
return caseLabelItem.caseLabelItem->getStartLoc();
1749+
1750+
case Kind::patternBinding:
1751+
return patternBinding->getLoc();
17161752
}
17171753
llvm_unreachable("invalid target type");
17181754
}

0 commit comments

Comments
 (0)