Skip to content

Commit ff59e5e

Browse files
committed
Sema: Collect PackElementExpr captures in CaptureInfoRequest
1 parent 670391a commit ff59e5e

File tree

3 files changed

+59
-35
lines changed

3 files changed

+59
-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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4262,7 +4262,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
42624262
ValueDecl *value = capture.getDecl();
42634263
auto existing = captures.find(value);
42644264
if (existing != captures.end()) {
4265-
existing->second = existing->second.mergeFlags(capture);
4265+
existing->second = existing->second.mergeFlags(capture.getFlags());
42664266
} else {
42674267
captures.insert(std::pair<ValueDecl *, CapturedValue>(value, capture));
42684268
}
@@ -4398,7 +4398,7 @@ TypeConverter::getLoweredLocalCaptures(SILDeclRef fn) {
43984398
// If we've already captured the same value already, just merge
43994399
// flags.
44004400
if (selfCapture && selfCapture->getDecl() == capture.getDecl()) {
4401-
selfCapture = selfCapture->mergeFlags(capture);
4401+
selfCapture = selfCapture->mergeFlags(capture.getFlags());
44024402
continue;
44034403

44044404
// 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
@@ -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::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+
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

Comments
 (0)