@@ -38,17 +38,18 @@ class FindCapturedVars : public ASTWalker {
38
38
SmallVector<CapturedValue, 4 > Captures;
39
39
llvm::SmallDenseMap<ValueDecl*, unsigned , 4 > captureEntryNumber;
40
40
41
- // / We track the pack expansion expressions in ForEachStmts, because
42
- // / their local generics remain in scope until the end of the statement .
43
- llvm::DenseSet<PackExpansionExpr *> ForEachPatternSequences ;
41
+ // / Opened element environments introduced by `for ... in repeat`
42
+ // / statements .
43
+ llvm::SetVector<GenericEnvironment *> VisitingForEachEnv ;
44
44
45
- // / A stack of pack element environments we're currently walking into.
46
- // / A reference to an element archetype defined by one of these is not
47
- // / a capture.
48
- llvm::SetVector<GenericEnvironment *> VisitingEnvironments;
45
+ // / Opened element environments introduced by `repeat` expressions.
46
+ llvm::SetVector<GenericEnvironment *> VisitingPackExpansionEnv;
49
47
50
- // / A set of pack element environments we've encountered that were not
48
+ // / A set of local generic environments we've encountered that were not
51
49
// / in the above stack; those are the captures.
50
+ // /
51
+ // / Once we can capture opened existentials, opened existential environments
52
+ // / can go here too.
52
53
llvm::SetVector<GenericEnvironment *> CapturedEnvironments;
53
54
54
55
SourceLoc GenericParamCaptureLoc;
@@ -166,7 +167,8 @@ class FindCapturedVars : public ASTWalker {
166
167
// outside the body of the current closure.
167
168
if (auto *element = t->getAs <ElementArchetypeType>()) {
168
169
auto *env = element->getGenericEnvironment ();
169
- if (VisitingEnvironments.count (env) == 0 )
170
+ if (VisitingForEachEnv.count (env) == 0 &&
171
+ VisitingPackExpansionEnv.count (env) == 0 )
170
172
CapturedEnvironments.insert (env);
171
173
}
172
174
@@ -200,7 +202,11 @@ class FindCapturedVars : public ASTWalker {
200
202
// / if invalid.
201
203
void addCapture (CapturedValue capture) {
202
204
auto VD = capture.getDecl ();
203
-
205
+ if (!VD) {
206
+ Captures.push_back (capture);
207
+ return ;
208
+ }
209
+
204
210
if (auto var = dyn_cast<VarDecl>(VD)) {
205
211
// `async let` variables cannot currently be captured.
206
212
if (var->isAsyncLet ()) {
@@ -244,6 +250,24 @@ class FindCapturedVars : public ASTWalker {
244
250
return MacroWalking::Expansion;
245
251
}
246
252
253
+ PreWalkResult<Expr *> walkToPackElementExpr (PackElementExpr *PEE) {
254
+ // A pack element reference expression like `each t` or `each f()`
255
+ // expands within the innermost pack expansion expression. If there
256
+ // isn't one, it's from an outer function, so we record the capture.
257
+ if (!VisitingPackExpansionEnv.empty ())
258
+ return Action::Continue (PEE);
259
+
260
+ unsigned Flags = 0 ;
261
+
262
+ // If the closure is noescape, then we can capture the pack element
263
+ // as noescape.
264
+ if (NoEscape)
265
+ Flags |= CapturedValue::IsNoEscape;
266
+
267
+ addCapture (CapturedValue (PEE, Flags));
268
+ return Action::SkipChildren (PEE);
269
+ }
270
+
247
271
PreWalkResult<Expr *> walkToDeclRefExpr (DeclRefExpr *DRE) {
248
272
auto *D = DRE->getDecl ();
249
273
@@ -377,7 +401,14 @@ class FindCapturedVars : public ASTWalker {
377
401
void propagateCaptures (CaptureInfo captureInfo, SourceLoc loc) {
378
402
for (auto capture : captureInfo.getCaptures ()) {
379
403
// If the decl was captured from us, it isn't captured *by* us.
380
- if (capture.getDecl ()->getDeclContext () == CurDC)
404
+ if (capture.getDecl () &&
405
+ capture.getDecl ()->getDeclContext () == CurDC)
406
+ continue ;
407
+
408
+ // If the inner closure is nested in a PackExpansionExpr, it's
409
+ // PackElementExpr captures are not our captures.
410
+ if (capture.getPackElement () &&
411
+ !VisitingPackExpansionEnv.empty ())
381
412
continue ;
382
413
383
414
// Compute adjusted flags.
@@ -392,7 +423,7 @@ class FindCapturedVars : public ASTWalker {
392
423
if (!NoEscape)
393
424
Flags &= ~CapturedValue::IsNoEscape;
394
425
395
- addCapture (CapturedValue ( capture.getDecl (), Flags, capture. getLoc () ));
426
+ addCapture (capture.mergeFlags ( Flags));
396
427
}
397
428
398
429
if (!HasGenericParamCaptures) {
@@ -603,6 +634,9 @@ class FindCapturedVars : public ASTWalker {
603
634
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
604
635
return walkToDeclRefExpr (DRE);
605
636
637
+ if (auto *PEE = dyn_cast<PackElementExpr>(E))
638
+ return walkToPackElementExpr (PEE);
639
+
606
640
// Look into lazy initializers.
607
641
if (auto *LIE = dyn_cast<LazyInitializerExpr>(E)) {
608
642
LIE->getSubExpr ()->walk (*this );
@@ -638,8 +672,8 @@ class FindCapturedVars : public ASTWalker {
638
672
639
673
if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
640
674
if (auto *env = expansion->getGenericEnvironment ()) {
641
- assert (VisitingEnvironments .count (env) == 0 );
642
- VisitingEnvironments .insert (env);
675
+ assert (VisitingPackExpansionEnv .count (env) == 0 );
676
+ VisitingPackExpansionEnv .insert (env);
643
677
}
644
678
}
645
679
@@ -649,13 +683,10 @@ class FindCapturedVars : public ASTWalker {
649
683
PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
650
684
if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
651
685
if (auto *env = expansion->getGenericEnvironment ()) {
652
- assert (env == VisitingEnvironments .back ());
686
+ assert (env == VisitingPackExpansionEnv .back ());
653
687
(void ) env;
654
688
655
- // If this is the pack expansion of a for .. in loop, the generic
656
- // environment remains in scope until the end of the loop.
657
- if (ForEachPatternSequences.count (expansion) == 0 )
658
- VisitingEnvironments.pop_back ();
689
+ VisitingPackExpansionEnv.pop_back ();
659
690
}
660
691
}
661
692
@@ -669,8 +700,8 @@ class FindCapturedVars : public ASTWalker {
669
700
if (auto *env = expansion->getGenericEnvironment ()) {
670
701
// Remember this generic environment, so that it remains on the
671
702
// visited stack until the end of the for .. in loop.
672
- assert (ForEachPatternSequences .count (expansion ) == 0 );
673
- ForEachPatternSequences .insert (expansion );
703
+ assert (VisitingForEachEnv .count (env ) == 0 );
704
+ VisitingForEachEnv .insert (env );
674
705
}
675
706
}
676
707
}
@@ -683,13 +714,10 @@ class FindCapturedVars : public ASTWalker {
683
714
if (auto *expansion =
684
715
dyn_cast<PackExpansionExpr>(forEachStmt->getParsedSequence ())) {
685
716
if (auto *env = expansion->getGenericEnvironment ()) {
686
- assert (ForEachPatternSequences.count (expansion) != 0 );
687
- ForEachPatternSequences.erase (expansion);
688
-
689
- // Clean up the generic environment bound by the for loop.
690
- assert (env == VisitingEnvironments.back ());
691
- VisitingEnvironments.pop_back ();
717
+ assert (VisitingForEachEnv.back () == env);
692
718
(void ) env;
719
+
720
+ VisitingForEachEnv.pop_back ();
693
721
}
694
722
}
695
723
}
0 commit comments