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