Skip to content

Commit 50af68d

Browse files
committed
[CSClosure] Handle pattern and sequence of for-in loop together
Let `visitForEachPattern` handle both pattern and the sequence expression associated with `for-in` loop because types in this situation flow in both directions: - From pattern to sequence, informing its element type e.g. `for i: Int8 in 0 ..< 8` - From sequence to pattern, when pattern has no type information.
1 parent 29ec113 commit 50af68d

File tree

1 file changed

+31
-19
lines changed

1 file changed

+31
-19
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,14 @@ class ClosureConstraintGenerator
302302
}
303303

304304
private:
305+
/// This method handles both pattern and the sequence expression
306+
/// associated with `for-in` loop because types in this situation
307+
/// flow in both directions:
308+
///
309+
/// - From pattern to sequence, informing its element type e.g.
310+
/// `for i: Int8 in 0 ..< 8`
311+
///
312+
/// - From sequence to pattern, when pattern has no type information.
305313
void visitForEachPattern(Pattern *pattern, ForEachStmt *forEachStmt) {
306314
auto &ctx = cs.getASTContext();
307315

@@ -340,11 +348,27 @@ class ClosureConstraintGenerator
340348
return;
341349
}
342350

343-
// Type of the sequence associated with for-each statement, should
344-
// be determined already.
351+
// Let's generate constraints for sequence associated with `for-in`
352+
// statement. We can't do that separately because pattern can inform
353+
// a type of the sequence e.g. `for in i: Int8 in 0 ..< 8 { ... }`
354+
345355
auto *sequenceExpr = forEachStmt->getSequence();
346356
auto *sequenceLocator = cs.getConstraintLocator(sequenceExpr);
347357

358+
{
359+
SolutionApplicationTarget target(
360+
sequenceExpr, closure, CTP_ForEachSequence,
361+
sequenceProto->getDeclaredInterfaceType(),
362+
/*isDiscarded=*/false);
363+
364+
if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
365+
hadError = true;
366+
return;
367+
}
368+
369+
cs.setSolutionApplicationTarget(sequenceExpr, target);
370+
}
371+
348372
Type sequenceType =
349373
cs.createTypeVariable(sequenceLocator, TVO_CanBindToNoEscape);
350374
// This "workaround" warrants an explanation for posterity.
@@ -597,31 +621,19 @@ class ClosureConstraintGenerator
597621
if (!isSupportedMultiStatementClosure())
598622
llvm_unreachable("Unsupported statement: ForEach");
599623

600-
bool isAsync = forEachStmt->getAwaitLoc().isValid();
601-
602624
auto *stmtLoc = cs.getConstraintLocator(locator);
603625

604-
auto *sequenceProto = getSequenceProtocol(
605-
cs.getASTContext(), forEachStmt->getForLoc(), isAsync);
606-
if (!sequenceProto) {
607-
hadError = true;
608-
return;
609-
}
610-
611626
SmallVector<ElementInfo, 4> elements;
612627

613-
// Sequence expression.
614-
{
615-
elements.push_back(makeElement(
616-
forEachStmt->getSequence(), stmtLoc,
617-
{sequenceProto->getDeclaredInterfaceType(), CTP_ForEachSequence}));
618-
}
619-
620628
// For-each pattern.
629+
//
630+
// Note that we don't record a sequence here, it would
631+
// be handled together with pattern because pattern can
632+
// inform a type of sequence element e.g. `for i: Int8 in 0 ..< 8`
621633
{
622634
Pattern *pattern =
623635
TypeChecker::resolvePattern(forEachStmt->getPattern(), closure,
624-
/*isStmtCondition*/ false);
636+
/*isStmtCondition=*/false);
625637

626638
if (!pattern) {
627639
hadError = true;

0 commit comments

Comments
 (0)