Skip to content

Commit 3801d16

Browse files
committed
ASTScope: Simplify representation of closures
Let's use a ClosureParametersScope for all closures, even those without an 'in' keyword. This eliminates the need for the ClosureBodyScope and WholeClosureScope. Also, let's move the lookup of capture list bindings from CaptureParametersScope to CaptureListScope. This eliminates the need for CaptureParametersScope to store a reference to the capture list, which allows us to remove the AbstractClosureScope base class entirely.
1 parent f898747 commit 3801d16

File tree

5 files changed

+81
-215
lines changed

5 files changed

+81
-215
lines changed

include/swift/AST/ASTScope.h

Lines changed: 18 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,9 +1393,7 @@ class ConditionalClausePatternUseScope final : public ASTScopeImpl {
13931393
};
13941394

13951395

1396-
/// Capture lists may contain initializer expressions
1397-
/// No local bindings here (other than closures in initializers);
1398-
/// rather include these in the params or body local bindings
1396+
/// Capture lists introduce local bindings.
13991397
class CaptureListScope final : public ASTScopeImpl {
14001398
public:
14011399
CaptureListExpr *const expr;
@@ -1416,63 +1414,17 @@ class CaptureListScope final : public ASTScopeImpl {
14161414
NullablePtr<Expr> getExprIfAny() const override { return expr; }
14171415
Expr *getExpr() const { return expr; }
14181416
NullablePtr<const void> getReferrent() const override;
1417+
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
1418+
DeclConsumer) const override;
14191419
};
14201420

1421-
// In order for compatibility with existing lookup, closures are represented
1422-
// by multiple scopes: An overall scope (including the part before the "in"
1423-
// and a body scope, including the part after the "in"
1424-
class AbstractClosureScope : public ASTScopeImpl {
1421+
/// For a closure with named parameters, this scope does the local bindings.
1422+
class ClosureParametersScope final : public ASTScopeImpl {
14251423
public:
1426-
NullablePtr<CaptureListExpr> captureList;
14271424
ClosureExpr *const closureExpr;
14281425

1429-
AbstractClosureScope(ClosureExpr *closureExpr,
1430-
NullablePtr<CaptureListExpr> captureList)
1431-
: captureList(captureList), closureExpr(closureExpr) {}
1432-
virtual ~AbstractClosureScope() {}
1433-
1434-
NullablePtr<ClosureExpr> getClosureIfClosureScope() const override;
1435-
NullablePtr<DeclContext> getDeclContext() const override {
1436-
return closureExpr;
1437-
}
1438-
NullablePtr<const void> addressForPrinting() const override {
1439-
return closureExpr;
1440-
}
1441-
};
1442-
1443-
class WholeClosureScope final : public AbstractClosureScope {
1444-
const BraceStmt *bodyWhenLastExpanded;
1445-
1446-
public:
1447-
WholeClosureScope(ClosureExpr *closureExpr,
1448-
NullablePtr<CaptureListExpr> captureList)
1449-
: AbstractClosureScope(closureExpr, captureList) {}
1450-
virtual ~WholeClosureScope() {}
1451-
1452-
protected:
1453-
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
1454-
void beCurrent() override;
1455-
bool isCurrentIfWasExpanded() const override;
1456-
1457-
private:
1458-
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
1459-
1460-
public:
1461-
std::string getClassName() const override;
1462-
SourceRange
1463-
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
1464-
NullablePtr<Expr> getExprIfAny() const override { return closureExpr; }
1465-
Expr *getExpr() const { return closureExpr; }
1466-
NullablePtr<const void> getReferrent() const override;
1467-
};
1468-
1469-
/// For a closure with named parameters, this scope does the local bindings.
1470-
/// Absent if no "in".
1471-
class ClosureParametersScope final : public AbstractClosureScope {
1472-
public:
1473-
ClosureParametersScope(ClosureExpr *closureExpr,
1474-
NullablePtr<CaptureListExpr> captureList)
1475-
: AbstractClosureScope(closureExpr, captureList) {}
1426+
ClosureParametersScope(ClosureExpr *closureExpr)
1427+
: closureExpr(closureExpr) {}
14761428
virtual ~ClosureParametersScope() {}
14771429

14781430
std::string getClassName() const override;
@@ -1486,35 +1438,25 @@ class ClosureParametersScope final : public AbstractClosureScope {
14861438
/// a capture of self.
14871439
NullablePtr<DeclContext> capturedSelfDC() const override;
14881440

1489-
protected:
1490-
ASTScopeImpl *expandSpecifically(ScopeCreator &) override;
1491-
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
1492-
DeclConsumer) const override;
1493-
Optional<bool> resolveIsCascadingUseForThisScope(
1494-
Optional<bool> isCascadingUse) const override;
1495-
};
1496-
1497-
// The body encompasses the code in the closure; the part after the "in" if
1498-
// there is an "in"
1499-
class ClosureBodyScope final : public AbstractClosureScope {
1500-
public:
1501-
ClosureBodyScope(ClosureExpr *closureExpr,
1502-
NullablePtr<CaptureListExpr> captureList)
1503-
: AbstractClosureScope(closureExpr, captureList) {}
1504-
virtual ~ClosureBodyScope() {}
1441+
NullablePtr<ClosureExpr> getClosureIfClosureScope() const override {
1442+
return closureExpr;
1443+
}
1444+
NullablePtr<DeclContext> getDeclContext() const override {
1445+
return closureExpr;
1446+
}
1447+
NullablePtr<Expr> getExprIfAny() const override { return closureExpr; }
1448+
Expr *getExpr() const { return closureExpr; }
1449+
NullablePtr<const void> getReferrent() const override;
15051450

15061451
protected:
15071452
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;
15081453

15091454
private:
15101455
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
15111456

1512-
public:
1513-
std::string getClassName() const override;
1514-
SourceRange
1515-
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
1516-
15171457
protected:
1458+
bool lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,
1459+
DeclConsumer) const override;
15181460
Optional<bool> resolveIsCascadingUseForThisScope(
15191461
Optional<bool> isCascadingUse) const override;
15201462
};

lib/AST/ASTScope.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,6 @@ NullablePtr<ClosureExpr> BraceStmtScope::parentClosureIfAny() const {
9696
NullablePtr<ClosureExpr> ASTScopeImpl::getClosureIfClosureScope() const {
9797
return nullptr;
9898
}
99-
NullablePtr<ClosureExpr>
100-
AbstractClosureScope::getClosureIfClosureScope() const {
101-
return closureExpr;
102-
}
10399

104100
// Conservative, because using precise info would be circular
105101
SourceRange
@@ -231,9 +227,7 @@ DEFINE_GET_CLASS_NAME(PatternEntryInitializerScope)
231227
DEFINE_GET_CLASS_NAME(ConditionalClauseScope)
232228
DEFINE_GET_CLASS_NAME(ConditionalClausePatternUseScope)
233229
DEFINE_GET_CLASS_NAME(CaptureListScope)
234-
DEFINE_GET_CLASS_NAME(WholeClosureScope)
235230
DEFINE_GET_CLASS_NAME(ClosureParametersScope)
236-
DEFINE_GET_CLASS_NAME(ClosureBodyScope)
237231
DEFINE_GET_CLASS_NAME(TopLevelCodeScope)
238232
DEFINE_GET_CLASS_NAME(SpecializeAttributeScope)
239233
DEFINE_GET_CLASS_NAME(DifferentiableAttributeScope)

lib/AST/ASTScopeCreation.cpp

Lines changed: 49 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -383,21 +383,51 @@ class ScopeCreator final {
383383

384384
void addExprToScopeTree(Expr *expr, ASTScopeImpl *parent) {
385385
// Use the ASTWalker to find buried captures and closures
386-
forEachClosureIn(expr, [&](NullablePtr<CaptureListExpr> captureList,
387-
ClosureExpr *closureExpr) {
388-
ifUniqueConstructExpandAndInsert<WholeClosureScope>(parent, closureExpr,
389-
captureList);
390-
});
386+
ASTScopeAssert(expr,
387+
"If looking for closures, must have an expression to search.");
388+
389+
/// AST walker that finds top-level closures in an expression.
390+
class ClosureFinder : public ASTWalker {
391+
ScopeCreator &scopeCreator;
392+
ASTScopeImpl *parent;
393+
394+
public:
395+
ClosureFinder(ScopeCreator &scopeCreator, ASTScopeImpl *parent)
396+
: scopeCreator(scopeCreator), parent(parent) {}
397+
398+
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
399+
if (auto *closure = dyn_cast<ClosureExpr>(E)) {
400+
scopeCreator
401+
.ifUniqueConstructExpandAndInsert<ClosureParametersScope>(
402+
parent, closure);
403+
return {false, E};
404+
}
405+
if (auto *capture = dyn_cast<CaptureListExpr>(E)) {
406+
scopeCreator
407+
.ifUniqueConstructExpandAndInsert<CaptureListScope>(
408+
parent, capture);
409+
return {false, E};
410+
}
411+
return {true, E};
412+
}
413+
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
414+
if (isa<BraceStmt>(S)) { // closures hidden in here
415+
return {true, S};
416+
}
417+
return {false, S};
418+
}
419+
std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override {
420+
return {false, P};
421+
}
422+
bool walkToDeclPre(Decl *D) override { return false; }
423+
bool walkToTypeReprPre(TypeRepr *T) override { return false; }
424+
bool walkToParameterListPre(ParameterList *PL) override { return false; }
425+
};
426+
427+
expr->walk(ClosureFinder(*this, parent));
391428
}
392429

393430
private:
394-
/// Find all of the (non-nested) closures (and associated capture lists)
395-
/// referenced within this expression.
396-
void forEachClosureIn(
397-
Expr *expr,
398-
function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
399-
foundClosure);
400-
401431
// A safe way to discover this, without creating a circular request.
402432
// Cannot call getAttachedPropertyWrappers.
403433
static bool hasAttachedPropertyWrapper(VarDecl *vd) {
@@ -1171,7 +1201,7 @@ NO_NEW_INSERTION_POINT(CaptureListScope)
11711201
NO_NEW_INSERTION_POINT(CaseStmtScope)
11721202
NO_NEW_INSERTION_POINT(CaseLabelItemScope)
11731203
NO_NEW_INSERTION_POINT(CaseStmtBodyScope)
1174-
NO_NEW_INSERTION_POINT(ClosureBodyScope)
1204+
NO_NEW_INSERTION_POINT(ClosureParametersScope)
11751205
NO_NEW_INSERTION_POINT(DefaultArgumentInitializerScope)
11761206
NO_NEW_INSERTION_POINT(DoStmtScope)
11771207
NO_NEW_INSERTION_POINT(DoCatchStmtScope)
@@ -1183,10 +1213,8 @@ NO_NEW_INSERTION_POINT(SubscriptDeclScope)
11831213
NO_NEW_INSERTION_POINT(SwitchStmtScope)
11841214
NO_NEW_INSERTION_POINT(VarDeclScope)
11851215
NO_NEW_INSERTION_POINT(WhileStmtScope)
1186-
NO_NEW_INSERTION_POINT(WholeClosureScope)
11871216

11881217
NO_EXPANSION(GenericParamScope)
1189-
NO_EXPANSION(ClosureParametersScope)
11901218
NO_EXPANSION(SpecializeAttributeScope)
11911219
NO_EXPANSION(DifferentiableAttributeScope)
11921220
NO_EXPANSION(ConditionalClausePatternUseScope)
@@ -1525,35 +1553,15 @@ void SubscriptDeclScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
15251553
scopeCreator.addChildrenForAllLocalizableAccessorsInSourceOrder(sub, params);
15261554
}
15271555

1528-
void WholeClosureScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
1529-
ScopeCreator &scopeCreator) {
1530-
if (auto *cl = captureList.getPtrOrNull())
1531-
scopeCreator.ensureUniqueThenConstructExpandAndInsert<CaptureListScope>(
1532-
this, cl);
1533-
ASTScopeImpl *bodyParent = this;
1534-
if (closureExpr->getInLoc().isValid())
1535-
bodyParent =
1536-
scopeCreator
1537-
.constructExpandAndInsertUncheckable<ClosureParametersScope>(
1538-
this, closureExpr, captureList);
1539-
scopeCreator.constructExpandAndInsertUncheckable<ClosureBodyScope>(
1540-
bodyParent, closureExpr, captureList);
1541-
}
1542-
15431556
void CaptureListScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
15441557
ScopeCreator &scopeCreator) {
1545-
// Patterns here are implicit, so need to dig out the intializers
1546-
for (const CaptureListEntry &captureListEntry : expr->getCaptureList()) {
1547-
for (unsigned patternEntryIndex = 0;
1548-
patternEntryIndex < captureListEntry.Init->getNumPatternEntries();
1549-
++patternEntryIndex) {
1550-
Expr *init = captureListEntry.Init->getInit(patternEntryIndex);
1551-
scopeCreator.addExprToScopeTree(init, this);
1552-
}
1553-
}
1558+
auto *closureExpr = expr->getClosureBody();
1559+
scopeCreator
1560+
.ifUniqueConstructExpandAndInsert<ClosureParametersScope>(
1561+
this, closureExpr);
15541562
}
15551563

1556-
void ClosureBodyScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
1564+
void ClosureParametersScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
15571565
ScopeCreator &scopeCreator) {
15581566
scopeCreator.addToScopeTree(closureExpr->getBody(), this);
15591567
}
@@ -1733,51 +1741,6 @@ bool ASTScopeImpl::isATypeDeclScope() const {
17331741
return pd && (isa<NominalTypeDecl>(pd) || isa<ExtensionDecl>(pd));
17341742
}
17351743

1736-
void ScopeCreator::forEachClosureIn(
1737-
Expr *expr, function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
1738-
foundClosure) {
1739-
ASTScopeAssert(expr,
1740-
"If looking for closures, must have an expression to search.");
1741-
1742-
/// AST walker that finds top-level closures in an expression.
1743-
class ClosureFinder : public ASTWalker {
1744-
function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
1745-
foundClosure;
1746-
1747-
public:
1748-
ClosureFinder(
1749-
function_ref<void(NullablePtr<CaptureListExpr>, ClosureExpr *)>
1750-
foundClosure)
1751-
: foundClosure(foundClosure) {}
1752-
1753-
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
1754-
if (auto *closure = dyn_cast<ClosureExpr>(E)) {
1755-
foundClosure(nullptr, closure);
1756-
return {false, E};
1757-
}
1758-
if (auto *capture = dyn_cast<CaptureListExpr>(E)) {
1759-
foundClosure(capture, capture->getClosureBody());
1760-
return {false, E};
1761-
}
1762-
return {true, E};
1763-
}
1764-
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
1765-
if (isa<BraceStmt>(S)) { // closures hidden in here
1766-
return {true, S};
1767-
}
1768-
return {false, S};
1769-
}
1770-
std::pair<bool, Pattern *> walkToPatternPre(Pattern *P) override {
1771-
return {false, P};
1772-
}
1773-
bool walkToDeclPre(Decl *D) override { return false; }
1774-
bool walkToTypeReprPre(TypeRepr *T) override { return false; }
1775-
bool walkToParameterListPre(ParameterList *PL) override { return false; }
1776-
};
1777-
1778-
expr->walk(ClosureFinder(foundClosure));
1779-
}
1780-
17811744
#pragma mark new operators
17821745
void *ASTScopeImpl::operator new(size_t bytes, const ASTContext &ctx,
17831746
unsigned alignment) {
@@ -1839,7 +1802,7 @@ GET_REFERRENT(VarDeclScope, getDecl())
18391802
GET_REFERRENT(GenericParamScope, paramList->getParams()[index])
18401803
GET_REFERRENT(AbstractStmtScope, getStmt())
18411804
GET_REFERRENT(CaptureListScope, getExpr())
1842-
GET_REFERRENT(WholeClosureScope, getExpr())
1805+
GET_REFERRENT(ClosureParametersScope, getExpr())
18431806
GET_REFERRENT(SpecializeAttributeScope, specializeAttr)
18441807
GET_REFERRENT(DifferentiableAttributeScope, differentiableAttr)
18451808
GET_REFERRENT(GenericTypeOrExtensionScope, portion->getReferrentOfScope(this));
@@ -1980,13 +1943,6 @@ bool PatternEntryDeclScope::isCurrentIfWasExpanded() const {
19801943
return getPatternEntry().getNumBoundVariables() == varCountWhenLastExpanded;
19811944
}
19821945

1983-
void WholeClosureScope::beCurrent() {
1984-
bodyWhenLastExpanded = closureExpr->getBody();
1985-
}
1986-
bool WholeClosureScope::isCurrentIfWasExpanded() const {
1987-
return bodyWhenLastExpanded == closureExpr->getBody();
1988-
}
1989-
19901946
#pragma mark getParentOfASTAncestorScopesToBeRescued
19911947
NullablePtr<ASTScopeImpl>
19921948
ASTScopeImpl::getParentOfASTAncestorScopesToBeRescued() {

lib/AST/ASTScopeLookup.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -424,18 +424,19 @@ bool PatternEntryInitializerScope::lookupLocalsOrMembers(
424424
return false;
425425
}
426426

427-
bool ClosureParametersScope::lookupLocalsOrMembers(
427+
bool CaptureListScope::lookupLocalsOrMembers(
428428
ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
429-
if (auto *cl = captureList.getPtrOrNull()) {
430-
CaptureListExpr *mutableCL =
431-
const_cast<CaptureListExpr *>(captureList.get());
432-
for (auto &e : mutableCL->getCaptureList()) {
433-
if (consumer.consume(
434-
{e.Var},
435-
DeclVisibilityKind::LocalVariable)) // or FunctionParameter??
436-
return true;
437-
}
429+
for (auto &e : expr->getCaptureList()) {
430+
if (consumer.consume(
431+
{e.Var},
432+
DeclVisibilityKind::LocalVariable)) // or FunctionParameter??
433+
return true;
438434
}
435+
return false;
436+
}
437+
438+
bool ClosureParametersScope::lookupLocalsOrMembers(
439+
ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
439440
for (auto param : *closureExpr->getParameters())
440441
if (consumer.consume({param}, DeclVisibilityKind::FunctionParameter))
441442
return true;
@@ -702,10 +703,6 @@ Optional<bool> ClosureParametersScope::resolveIsCascadingUseForThisScope(
702703
Optional<bool> isCascadingUse) const {
703704
return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, closureExpr);
704705
}
705-
Optional<bool> ClosureBodyScope::resolveIsCascadingUseForThisScope(
706-
Optional<bool> isCascadingUse) const {
707-
return ifUnknownIsCascadingUseAccordingTo(isCascadingUse, closureExpr);
708-
}
709706

710707
Optional<bool> PatternEntryInitializerScope::resolveIsCascadingUseForThisScope(
711708
Optional<bool> isCascadingUse) const {

0 commit comments

Comments
 (0)