Skip to content

Commit 992ffa6

Browse files
authored
Merge pull request #33981 from slavapestov/simplify-astscope-closure-representation
ASTScope: Simplify representation of closures
2 parents 4258267 + 3801d16 commit 992ffa6

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)