Skip to content

Commit 8679d34

Browse files
committed
Sema: Collect PackElementExpr captures in TypeChecker::computeCaptures()
1 parent ceb4c9c commit 8679d34

File tree

3 files changed

+58
-35
lines changed

3 files changed

+58
-35
lines changed

include/swift/AST/CaptureInfo.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,8 @@ class CapturedValue {
106106
/// values with decls are the only values that are able to be local captures.
107107
bool isLocalCapture() const;
108108

109-
CapturedValue mergeFlags(CapturedValue cv) {
110-
assert(Value.getPointer() == cv.Value.getPointer() &&
111-
"merging flags on two different value decls");
112-
return CapturedValue(
113-
Storage(Value.getPointer(), getFlags() & cv.getFlags()),
114-
Loc);
109+
CapturedValue mergeFlags(unsigned flags) const {
110+
return CapturedValue(Storage(Value.getPointer(), getFlags() & flags), Loc);
115111
}
116112

117113
ValueDecl *getDecl() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4238,7 +4238,6 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
42384238

42394239
collectCaptures = [&](CaptureInfo captureInfo, DeclContext *dc) {
42404240
assert(captureInfo.hasBeenComputed());
4241-
42424241
if (captureInfo.hasGenericParamCaptures())
42434242
capturesGenericParams = true;
42444243
if (captureInfo.hasDynamicSelfCapture())
@@ -4367,7 +4366,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
43674366
// If we've already captured the same value already, just merge
43684367
// flags.
43694368
if (selfCapture && selfCapture->getDecl() == capture.getDecl()) {
4370-
selfCapture = selfCapture->mergeFlags(capture);
4369+
selfCapture = selfCapture->mergeFlags(capture.getFlags());
43714370
continue;
43724371

43734372
// Otherwise, record the canonical self capture. It will appear

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,18 @@ class FindCapturedVars : public ASTWalker {
3838
SmallVector<CapturedValue, 4> Captures;
3939
llvm::SmallDenseMap<ValueDecl*, unsigned, 4> captureEntryNumber;
4040

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;
4444

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;
4947

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
5149
/// in the above stack; those are the captures.
50+
///
51+
/// Once we can capture opened existentials, opened existential environments
52+
/// can go here too.
5253
llvm::SetVector<GenericEnvironment *> CapturedEnvironments;
5354

5455
SourceLoc GenericParamCaptureLoc;
@@ -166,7 +167,8 @@ class FindCapturedVars : public ASTWalker {
166167
// outside the body of the current closure.
167168
if (auto *element = t->getAs<ElementArchetypeType>()) {
168169
auto *env = element->getGenericEnvironment();
169-
if (VisitingEnvironments.count(env) == 0)
170+
if (VisitingForEachEnv.count(env) == 0 &&
171+
VisitingPackExpansionEnv.count(env) == 0)
170172
CapturedEnvironments.insert(env);
171173
}
172174

@@ -200,7 +202,11 @@ class FindCapturedVars : public ASTWalker {
200202
/// if invalid.
201203
void addCapture(CapturedValue capture) {
202204
auto VD = capture.getDecl();
203-
205+
if (!VD) {
206+
Captures.push_back(capture);
207+
return;
208+
}
209+
204210
if (auto var = dyn_cast<VarDecl>(VD)) {
205211
// `async let` variables cannot currently be captured.
206212
if (var->isAsyncLet()) {
@@ -244,6 +250,24 @@ class FindCapturedVars : public ASTWalker {
244250
return MacroWalking::Expansion;
245251
}
246252

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+
247271
PreWalkResult<Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
248272
auto *D = DRE->getDecl();
249273

@@ -377,7 +401,14 @@ class FindCapturedVars : public ASTWalker {
377401
void propagateCaptures(CaptureInfo captureInfo, SourceLoc loc) {
378402
for (auto capture : captureInfo.getCaptures()) {
379403
// 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())
381412
continue;
382413

383414
// Compute adjusted flags.
@@ -392,7 +423,7 @@ class FindCapturedVars : public ASTWalker {
392423
if (!NoEscape)
393424
Flags &= ~CapturedValue::IsNoEscape;
394425

395-
addCapture(CapturedValue(capture.getDecl(), Flags, capture.getLoc()));
426+
addCapture(capture.mergeFlags(Flags));
396427
}
397428

398429
if (!HasGenericParamCaptures) {
@@ -603,6 +634,9 @@ class FindCapturedVars : public ASTWalker {
603634
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
604635
return walkToDeclRefExpr(DRE);
605636

637+
if (auto *PEE = dyn_cast<PackElementExpr>(E))
638+
return walkToPackElementExpr(PEE);
639+
606640
// Look into lazy initializers.
607641
if (auto *LIE = dyn_cast<LazyInitializerExpr>(E)) {
608642
LIE->getSubExpr()->walk(*this);
@@ -638,8 +672,8 @@ class FindCapturedVars : public ASTWalker {
638672

639673
if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
640674
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);
643677
}
644678
}
645679

@@ -649,13 +683,10 @@ class FindCapturedVars : public ASTWalker {
649683
PostWalkResult<Expr *> walkToExprPost(Expr *E) override {
650684
if (auto expansion = dyn_cast<PackExpansionExpr>(E)) {
651685
if (auto *env = expansion->getGenericEnvironment()) {
652-
assert(env == VisitingEnvironments.back());
686+
assert(env == VisitingPackExpansionEnv.back());
653687
(void) env;
654688

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();
659690
}
660691
}
661692

@@ -669,8 +700,8 @@ class FindCapturedVars : public ASTWalker {
669700
if (auto *env = expansion->getGenericEnvironment()) {
670701
// Remember this generic environment, so that it remains on the
671702
// 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);
674705
}
675706
}
676707
}
@@ -683,13 +714,10 @@ class FindCapturedVars : public ASTWalker {
683714
if (auto *expansion =
684715
dyn_cast<PackExpansionExpr>(forEachStmt->getParsedSequence())) {
685716
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);
692718
(void) env;
719+
720+
VisitingForEachEnv.pop_back();
693721
}
694722
}
695723
}

0 commit comments

Comments
 (0)