@@ -39,17 +39,18 @@ class FindCapturedVars : public ASTWalker {
3939 SmallVector<CapturedValue, 4 > Captures;
4040 llvm::SmallDenseMap<ValueDecl*, unsigned , 4 > captureEntryNumber;
4141
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 ;
4545
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;
5048
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
5250 // / in the above stack; those are the captures.
51+ // /
52+ // / Once we can capture opened existentials, opened existential environments
53+ // / can go here too.
5354 llvm::SetVector<GenericEnvironment *> CapturedEnvironments;
5455
5556 SourceLoc GenericParamCaptureLoc;
@@ -167,7 +168,8 @@ class FindCapturedVars : public ASTWalker {
167168 // outside the body of the current closure.
168169 if (auto *element = t->getAs <ElementArchetypeType>()) {
169170 auto *env = element->getGenericEnvironment ();
170- if (VisitingEnvironments.count (env) == 0 )
171+ if (VisitingForEachEnv.count (env) == 0 &&
172+ VisitingPackExpansionEnv.count (env) == 0 )
171173 CapturedEnvironments.insert (env);
172174 }
173175
@@ -201,7 +203,11 @@ class FindCapturedVars : public ASTWalker {
201203 // / if invalid.
202204 void addCapture (CapturedValue capture) {
203205 auto VD = capture.getDecl ();
204-
206+ if (!VD) {
207+ Captures.push_back (capture);
208+ return ;
209+ }
210+
205211 if (auto var = dyn_cast<VarDecl>(VD)) {
206212 // `async let` variables cannot currently be captured.
207213 if (var->isAsyncLet ()) {
@@ -245,6 +251,24 @@ class FindCapturedVars : public ASTWalker {
245251 return MacroWalking::Expansion;
246252 }
247253
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::Continue (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+
248272 PreWalkResult<Expr *> walkToDeclRefExpr (DeclRefExpr *DRE) {
249273 auto *D = DRE->getDecl ();
250274
@@ -378,7 +402,14 @@ class FindCapturedVars : public ASTWalker {
378402 void propagateCaptures (CaptureInfo captureInfo, SourceLoc loc) {
379403 for (auto capture : captureInfo.getCaptures ()) {
380404 // 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 ())
382413 continue ;
383414
384415 // Compute adjusted flags.
@@ -393,7 +424,7 @@ class FindCapturedVars : public ASTWalker {
393424 if (!NoEscape)
394425 Flags &= ~CapturedValue::IsNoEscape;
395426
396- addCapture (CapturedValue ( capture.getDecl (), Flags, capture. getLoc () ));
427+ addCapture (capture.mergeFlags ( Flags));
397428 }
398429
399430 if (!HasGenericParamCaptures) {
@@ -609,6 +640,9 @@ class FindCapturedVars : public ASTWalker {
609640 if (auto *DRE = dyn_cast<DeclRefExpr>(E))
610641 return walkToDeclRefExpr (DRE);
611642
643+ if (auto *PEE = dyn_cast<PackElementExpr>(E))
644+ return walkToPackElementExpr (PEE);
645+
612646 // Look into lazy initializers.
613647 if (auto *LIE = dyn_cast<LazyInitializerExpr>(E)) {
614648 LIE->getSubExpr ()->walk (*this );
@@ -644,8 +678,8 @@ class FindCapturedVars : public ASTWalker {
644678
645679 if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
646680 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);
649683 }
650684 }
651685
@@ -655,13 +689,10 @@ class FindCapturedVars : public ASTWalker {
655689 PostWalkResult<Expr *> walkToExprPost (Expr *E) override {
656690 if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
657691 if (auto *env = expansion->getGenericEnvironment ()) {
658- assert (env == VisitingEnvironments .back ());
692+ assert (env == VisitingPackExpansionEnv .back ());
659693 (void ) env;
660694
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 ();
665696 }
666697 }
667698
@@ -675,8 +706,8 @@ class FindCapturedVars : public ASTWalker {
675706 if (auto *env = expansion->getGenericEnvironment ()) {
676707 // Remember this generic environment, so that it remains on the
677708 // 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 );
680711 }
681712 }
682713 }
@@ -689,13 +720,10 @@ class FindCapturedVars : public ASTWalker {
689720 if (auto *expansion =
690721 dyn_cast<PackExpansionExpr>(forEachStmt->getParsedSequence ())) {
691722 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);
698724 (void ) env;
725+
726+ VisitingForEachEnv.pop_back ();
699727 }
700728 }
701729 }
0 commit comments