Skip to content

Commit 72caaa8

Browse files
committed
[ConstraintSystem] Solve where clauses of for-in loops separately
Doing so fits better into conjunction model which leads to more granular control over what variables are brought into scope during `where` clause expression checking. These changes also remove "one-way bind" flag from "for-in" statement target.
1 parent 8edf870 commit 72caaa8

File tree

5 files changed

+30
-20
lines changed

5 files changed

+30
-20
lines changed

include/swift/Sema/SyntacticElementTarget.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class SyntacticElementTarget {
147147
ForEachStmt *stmt;
148148
DeclContext *dc;
149149
Pattern *pattern;
150-
bool bindPatternVarsOneWay;
150+
bool ignoreWhereClause;
151151
ForEachStmtInfo info;
152152
} forEachStmt;
153153

@@ -227,11 +227,11 @@ class SyntacticElementTarget {
227227
}
228228

229229
SyntacticElementTarget(ForEachStmt *stmt, DeclContext *dc,
230-
bool bindPatternVarsOneWay)
230+
bool ignoreWhereClause)
231231
: kind(Kind::forEachStmt) {
232232
forEachStmt.stmt = stmt;
233233
forEachStmt.dc = dc;
234-
forEachStmt.bindPatternVarsOneWay = bindPatternVarsOneWay;
234+
forEachStmt.ignoreWhereClause = ignoreWhereClause;
235235
}
236236

237237
/// Form a target for the initialization of a pattern from an expression.
@@ -249,7 +249,7 @@ class SyntacticElementTarget {
249249
/// Form a target for a for-in loop.
250250
static SyntacticElementTarget forForEachStmt(ForEachStmt *stmt,
251251
DeclContext *dc,
252-
bool bindPatternVarsOneWay);
252+
bool ignoreWhereClause = false);
253253

254254
/// Form a target for a property with an attached property wrapper that is
255255
/// initialized out-of-line.
@@ -469,10 +469,6 @@ class SyntacticElementTarget {
469469
bool shouldBindPatternVarsOneWay() const {
470470
if (kind == Kind::expression)
471471
return expression.bindPatternVarsOneWay;
472-
473-
if (kind == Kind::forEachStmt)
474-
return forEachStmt.bindPatternVarsOneWay;
475-
476472
return false;
477473
}
478474

@@ -521,6 +517,11 @@ class SyntacticElementTarget {
521517
return expression.initialization.patternBindingIndex;
522518
}
523519

520+
bool ignoreForEachWhereClause() const {
521+
assert(isForEachStmt());
522+
return forEachStmt.ignoreWhereClause;
523+
}
524+
524525
const ForEachStmtInfo &getForEachStmtInfo() const {
525526
assert(isForEachStmt());
526527
return forEachStmt.info;

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4546,12 +4546,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
45464546
}
45474547

45484548
// Generate constraints for the "where" expression, if there is one.
4549-
if (auto *whereExpr = stmt->getWhere()) {
4550-
auto *boolDecl = dc->getASTContext().getBoolDecl();
4551-
if (!boolDecl)
4552-
return llvm::None;
4553-
4554-
Type boolType = boolDecl->getDeclaredInterfaceType();
4549+
auto *whereExpr = stmt->getWhere();
4550+
if (whereExpr && !target.ignoreForEachWhereClause()) {
4551+
Type boolType = dc->getASTContext().getBoolType();
45554552
if (!boolType)
45564553
return llvm::None;
45574554

lib/Sema/CSSyntacticElement.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ class SyntacticElementConstraintGenerator
631631
void visitForEachPattern(Pattern *pattern, ForEachStmt *forEachStmt) {
632632
auto target = SyntacticElementTarget::forForEachStmt(
633633
forEachStmt, context.getAsDeclContext(),
634-
/*bindTypeVarsOneWay=*/false);
634+
/*ignoreWhereClause=*/true);
635635

636636
if (cs.generateConstraints(target)) {
637637
hadError = true;
@@ -959,6 +959,20 @@ class SyntacticElementConstraintGenerator
959959
// they would be handled together with pattern because pattern can
960960
// inform a type of sequence element e.g. `for i: Int8 in 0 ..< 8`
961961
elements.push_back(makeElement(forEachStmt->getPattern(), stmtLoc));
962+
963+
// Where clause if any.
964+
if (auto *where = forEachStmt->getWhere()) {
965+
Type boolType = cs.getASTContext().getBoolType();
966+
if (!boolType) {
967+
hadError = true;
968+
return;
969+
}
970+
971+
ContextualTypeInfo context(boolType, CTP_Condition);
972+
elements.push_back(
973+
makeElement(where, stmtLoc, context, /*isDiscarded=*/false));
974+
}
975+
962976
// Body of the `for-in` loop.
963977
elements.push_back(makeElement(forEachStmt->getBody(), stmtLoc));
964978

lib/Sema/SyntacticElementTarget.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,8 @@ SyntacticElementTarget SyntacticElementTarget::forInitialization(
178178

179179
SyntacticElementTarget
180180
SyntacticElementTarget::forForEachStmt(ForEachStmt *stmt, DeclContext *dc,
181-
bool bindPatternVarsOneWay) {
182-
SyntacticElementTarget target(
183-
stmt, dc, bindPatternVarsOneWay || bool(stmt->getWhere()));
181+
bool ignoreWhereClause) {
182+
SyntacticElementTarget target(stmt, dc, ignoreWhereClause);
184183
return target;
185184
}
186185

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
901901
return true;
902902
};
903903

904-
auto target = SyntacticElementTarget::forForEachStmt(
905-
stmt, dc, /*bindPatternVarsOneWay=*/false);
904+
auto target = SyntacticElementTarget::forForEachStmt(stmt, dc);
906905
if (!typeCheckTarget(target))
907906
return failed();
908907

0 commit comments

Comments
 (0)