@@ -302,6 +302,14 @@ class ClosureConstraintGenerator
302
302
}
303
303
304
304
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.
305
313
void visitForEachPattern (Pattern *pattern, ForEachStmt *forEachStmt) {
306
314
auto &ctx = cs.getASTContext ();
307
315
@@ -340,11 +348,27 @@ class ClosureConstraintGenerator
340
348
return ;
341
349
}
342
350
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
+
345
355
auto *sequenceExpr = forEachStmt->getSequence ();
346
356
auto *sequenceLocator = cs.getConstraintLocator (sequenceExpr);
347
357
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
+
348
372
Type sequenceType =
349
373
cs.createTypeVariable (sequenceLocator, TVO_CanBindToNoEscape);
350
374
// This "workaround" warrants an explanation for posterity.
@@ -597,31 +621,19 @@ class ClosureConstraintGenerator
597
621
if (!isSupportedMultiStatementClosure ())
598
622
llvm_unreachable (" Unsupported statement: ForEach" );
599
623
600
- bool isAsync = forEachStmt->getAwaitLoc ().isValid ();
601
-
602
624
auto *stmtLoc = cs.getConstraintLocator (locator);
603
625
604
- auto *sequenceProto = getSequenceProtocol (
605
- cs.getASTContext (), forEachStmt->getForLoc (), isAsync);
606
- if (!sequenceProto) {
607
- hadError = true ;
608
- return ;
609
- }
610
-
611
626
SmallVector<ElementInfo, 4 > elements;
612
627
613
- // Sequence expression.
614
- {
615
- elements.push_back (makeElement (
616
- forEachStmt->getSequence (), stmtLoc,
617
- {sequenceProto->getDeclaredInterfaceType (), CTP_ForEachSequence}));
618
- }
619
-
620
628
// 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`
621
633
{
622
634
Pattern *pattern =
623
635
TypeChecker::resolvePattern (forEachStmt->getPattern (), closure,
624
- /* isStmtCondition*/ false );
636
+ /* isStmtCondition= */ false );
625
637
626
638
if (!pattern) {
627
639
hadError = true ;
0 commit comments