Skip to content

Commit ef5689b

Browse files
authored
Merge pull request swiftlang#27758 from CodaFi/a-pattern-of-deescalation
2 parents e69fa3b + 3b82994 commit ef5689b

33 files changed

+217
-182
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,8 +1270,7 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
12701270
PatternEntryInitializerScope(PatternBindingDecl *pbDecl, unsigned entryIndex,
12711271
DeclVisibilityKind vis)
12721272
: AbstractPatternEntryScope(pbDecl, entryIndex, vis),
1273-
initAsWrittenWhenCreated(
1274-
pbDecl->getPatternList()[entryIndex].getOriginalInit()) {}
1273+
initAsWrittenWhenCreated(pbDecl->getOriginalInit(entryIndex)) {}
12751274
virtual ~PatternEntryInitializerScope() {}
12761275

12771276
protected:

include/swift/AST/Decl.h

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ namespace swift {
9393
class VarDecl;
9494
class OpaqueReturnTypeRepr;
9595

96+
namespace ast_scope {
97+
class AbstractPatternEntryScope;
98+
class PatternEntryDeclScope;
99+
class PatternEntryInitializerScope;
100+
} // namespace ast_scope
101+
96102
enum class DeclKind : uint8_t {
97103
#define DECL(Id, Parent) Id,
98104
#define LAST_DECL(Id) Last_Decl = Id,
@@ -1929,8 +1935,14 @@ class PatternBindingEntry {
19291935
/// Values captured by this initializer.
19301936
CaptureInfo Captures;
19311937

1938+
friend class Parser;
19321939
friend class PatternBindingInitializer;
1940+
friend class PatternBindingDecl;
1941+
friend class ast_scope::AbstractPatternEntryScope;
1942+
friend class ast_scope::PatternEntryDeclScope;
1943+
friend class ast_scope::PatternEntryInitializerScope;
19331944

1945+
private:
19341946
// FIXME: This API is transitional. Once the callers of
19351947
// typeCheckPatternBinding are requestified, merge this bit with
19361948
// Flags::Checked.
@@ -1952,6 +1964,7 @@ class PatternBindingEntry {
19521964
: PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
19531965
InitContextAndFlags({InitContext, None}) {}
19541966

1967+
private:
19551968
Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
19561969
void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }
19571970

@@ -2051,6 +2064,8 @@ class PatternBindingEntry {
20512064
CaptureInfo getCaptureInfo() const { return Captures; }
20522065
void setCaptureInfo(CaptureInfo captures) { Captures = captures; }
20532066

2067+
unsigned getNumBoundVariables() const;
2068+
20542069
private:
20552070
SourceLoc getLastAccessorEndLoc() const;
20562071
};
@@ -2136,6 +2151,9 @@ class PatternBindingDecl final : public Decl,
21362151
Expr *getExecutableInit(unsigned i) const {
21372152
return getPatternList()[i].getExecutableInit();
21382153
}
2154+
Expr *getOriginalInit(unsigned i) const {
2155+
return getPatternList()[i].getOriginalInit();
2156+
}
21392157

21402158
SourceRange getOriginalInitRange(unsigned i) const {
21412159
return getPatternList()[i].getOriginalInitRange();
@@ -2172,13 +2190,6 @@ class PatternBindingDecl final : public Decl,
21722190
/// and "c" and "d" will have index 1 since they correspond to the second one.
21732191
unsigned getPatternEntryIndexForVarDecl(const VarDecl *VD) const;
21742192

2175-
/// Return the PatternEntry (a pattern + initializer pair) for the specified
2176-
/// VarDecl.
2177-
const PatternBindingEntry &getPatternEntryForVarDecl(
2178-
const VarDecl *VD) const {
2179-
return getPatternList()[getPatternEntryIndexForVarDecl(VD)];
2180-
}
2181-
21822193
bool isInitializerChecked(unsigned i) const {
21832194
return getPatternList()[i].isInitializerChecked();
21842195
}
@@ -2201,7 +2212,7 @@ class PatternBindingDecl final : public Decl,
22012212
/// Determines whether this binding either has an initializer expression, or is
22022213
/// default initialized, without performing any type checking on it.
22032214
bool isDefaultInitializable() const {
2204-
for (unsigned i = 0, e = getNumPatternEntries(); i < e; ++i)
2215+
for (unsigned i : range(getNumPatternEntries()))
22052216
if (!isDefaultInitializable(i))
22062217
return false;
22072218

@@ -2210,11 +2221,25 @@ class PatternBindingDecl final : public Decl,
22102221

22112222
/// Can the pattern at index i be default initialized?
22122223
bool isDefaultInitializable(unsigned i) const;
2213-
2224+
2225+
/// Does this pattern have a user-provided initializer expression?
2226+
bool isExplicitlyInitialized(unsigned i) const;
2227+
2228+
/// Whether the pattern entry at the given index can generate a string
2229+
/// representation of its initializer expression.
2230+
bool hasInitStringRepresentation(unsigned i) const {
2231+
return getPatternList()[i].hasInitStringRepresentation();
2232+
}
2233+
2234+
SourceLoc getEqualLoc(unsigned i) const;
2235+
22142236
/// When the pattern binding contains only a single variable with no
22152237
/// destructuring, retrieve that variable.
22162238
VarDecl *getSingleVar() const;
22172239

2240+
/// Return the first variable initialized by the pattern at the given index.
2241+
VarDecl *getAnchoringVarDecl(unsigned i) const;
2242+
22182243
bool isStatic() const { return Bits.PatternBindingDecl.IsStatic; }
22192244
void setStatic(bool s) { Bits.PatternBindingDecl.IsStatic = s; }
22202245
SourceLoc getStaticLoc() const { return StaticLoc; }
@@ -2229,6 +2254,14 @@ class PatternBindingDecl final : public Decl,
22292254
/// Is the pattern binding entry for this variable currently being computed?
22302255
bool isComputingPatternBindingEntry(const VarDecl *vd) const;
22312256

2257+
/// Gets the text of the initializer expression for the pattern entry at the
2258+
/// given index, stripping out inactive branches of any #ifs inside the
2259+
/// expression.
2260+
StringRef getInitStringRepresentation(unsigned i,
2261+
SmallVectorImpl<char> &scratch) const {
2262+
return getPatternList()[i].getInitStringRepresentation(scratch);
2263+
}
2264+
22322265
static bool classof(const Decl *D) {
22332266
return D->getKind() == DeclKind::PatternBinding;
22342267
}
@@ -4981,15 +5014,19 @@ class VarDecl : public AbstractStorageDecl {
49815014
/// binding has no initial value, this returns null.
49825015
///
49835016
Expr *getParentInitializer() const {
4984-
if (auto *PBD = getParentPatternBinding())
4985-
return PBD->getPatternEntryForVarDecl(this).getInit();
5017+
if (auto *PBD = getParentPatternBinding()) {
5018+
const auto i = PBD->getPatternEntryIndexForVarDecl(this);
5019+
return PBD->getInit(i);
5020+
}
49865021
return nullptr;
49875022
}
49885023

49895024
/// Whether there exists an initializer for this \c VarDecl.
49905025
bool isParentInitialized() const {
4991-
if (auto *PBD = getParentPatternBinding())
4992-
return PBD->getPatternEntryForVarDecl(this).isInitialized();
5026+
if (auto *PBD = getParentPatternBinding()) {
5027+
const auto i = PBD->getPatternEntryIndexForVarDecl(this);
5028+
return PBD->isInitialized(i);
5029+
}
49935030
return false;
49945031
}
49955032

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -895,20 +895,20 @@ namespace {
895895
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
896896
printCommon(PBD, "pattern_binding_decl");
897897

898-
for (auto entry : PBD->getPatternList()) {
898+
for (auto idx : range(PBD->getNumPatternEntries())) {
899899
OS << '\n';
900-
printRec(entry.getPattern());
901-
if (entry.getOriginalInit()) {
900+
printRec(PBD->getPattern(idx));
901+
if (PBD->getOriginalInit(idx)) {
902902
OS << '\n';
903903
OS.indent(Indent + 2);
904904
OS << "Original init:\n";
905-
printRec(entry.getOriginalInit());
905+
printRec(PBD->getOriginalInit(idx));
906906
}
907-
if (entry.getInit()) {
907+
if (PBD->getInit(idx)) {
908908
OS << '\n';
909909
OS.indent(Indent + 2);
910910
OS << "Processed init:\n";
911-
printRec(entry.getInit());
911+
printRec(PBD->getInit(idx));
912912
}
913913
}
914914
PrintWithColorRAII(OS, ParenthesisColor) << ')';

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,8 +1606,8 @@ namespace {
16061606
/// least one name, which is probably a reasonable assumption but may
16071607
/// not be adequately enforced.
16081608
static Optional<VarDecl*> findFirstVariable(PatternBindingDecl *binding) {
1609-
for (auto entry : binding->getPatternList()) {
1610-
auto var = FindFirstVariable().visit(entry.getPattern());
1609+
for (auto idx : range(binding->getNumPatternEntries())) {
1610+
auto var = FindFirstVariable().visit(binding->getPattern(idx));
16111611
if (var) return var;
16121612
}
16131613
// Pattern-binding bound without variables exists in erroneous code, e.g.

lib/AST/ASTPrinter.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,8 +1665,8 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
16651665
// attributes can only be retrieved from the inside VarDecls.
16661666
if (auto *PD = dyn_cast<PatternBindingDecl>(D)) {
16671667
auto ShouldPrint = false;
1668-
for (auto entry : PD->getPatternList()) {
1669-
ShouldPrint |= shouldPrint(entry.getPattern(), Options);
1668+
for (auto idx : range(PD->getNumPatternEntries())) {
1669+
ShouldPrint |= shouldPrint(PD->getPattern(idx), Options);
16701670
if (ShouldPrint)
16711671
return true;
16721672
}
@@ -2162,8 +2162,8 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
21622162
// variables are immutable, and if so, we print as 'let'. This allows us to
21632163
// handle the 'let x = 4' case properly at least.
21642164
const VarDecl *anyVar = nullptr;
2165-
for (auto entry : decl->getPatternList()) {
2166-
entry.getPattern()->forEachVariable([&](VarDecl *V) {
2165+
for (auto idx : range(decl->getNumPatternEntries())) {
2166+
decl->getPattern(idx)->forEachVariable([&](VarDecl *V) {
21672167
anyVar = V;
21682168
});
21692169
if (anyVar) break;
@@ -2190,29 +2190,29 @@ void PrintAST::visitPatternBindingDecl(PatternBindingDecl *decl) {
21902190
}
21912191

21922192
bool isFirst = true;
2193-
for (auto &entry : decl->getPatternList()) {
2194-
if (!shouldPrintPattern(entry.getPattern()))
2193+
for (auto idx : range(decl->getNumPatternEntries())) {
2194+
auto *pattern = decl->getPattern(idx);
2195+
if (!shouldPrintPattern(pattern))
21952196
continue;
21962197
if (isFirst)
21972198
isFirst = false;
21982199
else
21992200
Printer << ", ";
22002201

2201-
printPattern(entry.getPattern());
2202+
printPattern(pattern);
22022203

22032204
// We also try to print type for named patterns, e.g. var Field = 10;
22042205
// and tuple patterns, e.g. var (T1, T2) = (10, 10)
2205-
if (isa<NamedPattern>(entry.getPattern()) ||
2206-
isa<TuplePattern>(entry.getPattern())) {
2207-
printPatternType(entry.getPattern());
2206+
if (isa<NamedPattern>(pattern) || isa<TuplePattern>(pattern)) {
2207+
printPatternType(pattern);
22082208
}
22092209

22102210
if (Options.VarInitializers) {
2211-
auto vd = entry.getAnchoringVarDecl();
2212-
if (entry.hasInitStringRepresentation() &&
2211+
auto *vd = decl->getAnchoringVarDecl(idx);
2212+
if (decl->hasInitStringRepresentation(idx) &&
22132213
vd->isInitExposedToClients()) {
22142214
SmallString<128> scratch;
2215-
Printer << " = " << entry.getInitStringRepresentation(scratch);
2215+
Printer << " = " << decl->getInitStringRepresentation(idx, scratch);
22162216
}
22172217
}
22182218

@@ -3401,7 +3401,7 @@ bool Decl::shouldPrintInContext(const PrintOptions &PO) const {
34013401
if (auto pbd = dyn_cast<PatternBindingDecl>(this)) {
34023402
if (pbd->getPatternList().size() == 1) {
34033403
auto pattern =
3404-
pbd->getPatternList()[0].getPattern()->getSemanticsProvidingPattern();
3404+
pbd->getPattern(0)->getSemanticsProvidingPattern();
34053405
if (auto named = dyn_cast<NamedPattern>(pattern)) {
34063406
if (!named->getDecl()->hasStorage())
34073407
return false;

lib/AST/ASTScope.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,7 @@ NullablePtr<DeclContext> CaptureListScope::getDeclContext() const {
190190
}
191191

192192
NullablePtr<DeclContext> AttachedPropertyWrapperScope::getDeclContext() const {
193-
return decl->getParentPatternBinding()
194-
->getPatternList()
195-
.front()
196-
.getInitContext();
193+
return decl->getParentPatternBinding()->getInitContext(0);
197194
}
198195

199196
NullablePtr<DeclContext> AbstractFunctionDeclScope::getDeclContext() const {

lib/AST/ASTScopeCreation.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -920,16 +920,15 @@ class NodeAdder
920920
isInTypeDecl ? DeclVisibilityKind::MemberOfCurrentNominal
921921
: DeclVisibilityKind::LocalVariable;
922922
auto *insertionPoint = parentScope;
923-
for (unsigned i = 0; i < patternBinding->getPatternList().size(); ++i) {
923+
for (auto i : range(patternBinding->getNumPatternEntries())) {
924924
// TODO: Won't need to do so much work to avoid creating one without
925925
// a SourceRange once parser is fixed to not create two
926926
// PatternBindingDecls with same locaiton and getSourceRangeOfThisASTNode
927927
// for PatternEntryDeclScope is simplified to use the PatternEntry's
928928
// source range.
929-
auto &patternEntry = patternBinding->getPatternList()[i];
930-
if (!patternEntry.getOriginalInit()) {
929+
if (!patternBinding->getOriginalInit(i)) {
931930
bool found = false;
932-
patternEntry.getPattern()->forEachVariable([&](VarDecl *vd) {
931+
patternBinding->getPattern(i)->forEachVariable([&](VarDecl *vd) {
933932
if (!vd->isImplicit())
934933
found = true;
935934
else
@@ -1913,27 +1912,22 @@ bool TopLevelCodeScope::isCurrentIfWasExpanded() const {
19131912
// Try to avoid the work of counting
19141913
static const bool assumeVarsDoNotGetAdded = true;
19151914

1916-
static unsigned countVars(const PatternBindingEntry &entry) {
1917-
unsigned varCount = 0;
1918-
entry.getPattern()->forEachVariable([&](VarDecl *) { ++varCount; });
1919-
return varCount;
1920-
}
1921-
19221915
void PatternEntryDeclScope::beCurrent() {
19231916
initWhenLastExpanded = getPatternEntry().getOriginalInit();
19241917
if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded)
19251918
return;
1926-
varCountWhenLastExpanded = countVars(getPatternEntry());
1919+
varCountWhenLastExpanded = getPatternEntry().getNumBoundVariables();
19271920
}
19281921
bool PatternEntryDeclScope::isCurrentIfWasExpanded() const {
19291922
if (initWhenLastExpanded != getPatternEntry().getOriginalInit())
19301923
return false;
19311924
if (assumeVarsDoNotGetAdded && varCountWhenLastExpanded) {
1932-
ASTScopeAssert(varCountWhenLastExpanded == countVars(getPatternEntry()),
1925+
ASTScopeAssert(varCountWhenLastExpanded ==
1926+
getPatternEntry().getNumBoundVariables(),
19331927
"Vars were not supposed to be added to a pattern entry.");
19341928
return true;
19351929
}
1936-
return countVars(getPatternEntry()) == varCountWhenLastExpanded;
1930+
return getPatternEntry().getNumBoundVariables() == varCountWhenLastExpanded;
19371931
}
19381932

19391933
void WholeClosureScope::beCurrent() {
@@ -2060,8 +2054,8 @@ class LocalizableDeclContextCollector : public ASTWalker {
20602054
}
20612055

20622056
void recordInitializers(PatternBindingDecl *pbd) {
2063-
for (auto entry : pbd->getPatternList())
2064-
record(entry.getInitContext());
2057+
for (auto idx : range(pbd->getNumPatternEntries()))
2058+
record(pbd->getInitContext(idx));
20652059
}
20662060

20672061
void catchForDebugging(Decl *D, const char *file, const unsigned line) {

lib/AST/ASTScopeLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ bool PatternEntryInitializerScope::lookupLocalsOrMembers(
457457
ArrayRef<const ASTScopeImpl *>, DeclConsumer consumer) const {
458458
// 'self' is available within the pattern initializer of a 'lazy' variable.
459459
auto *initContext = cast_or_null<PatternBindingInitializer>(
460-
decl->getPatternList()[0].getInitContext());
460+
decl->getInitContext(0));
461461
if (initContext) {
462462
if (auto *selfParam = initContext->getImplicitSelfDecl()) {
463463
return consumer.consume({selfParam},

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,8 +2357,8 @@ class Verifier : public ASTWalker {
23572357

23582358
void verifyChecked(PatternBindingDecl *binding) {
23592359
// Look at all of the VarDecls being bound.
2360-
for (auto entry : binding->getPatternList())
2361-
if (auto *P = entry.getPattern())
2360+
for (auto idx : range(binding->getNumPatternEntries()))
2361+
if (auto *P = binding->getPattern(idx))
23622362
P->forEachVariable([&](VarDecl *VD) {
23632363
// ParamDecls never get PBD's.
23642364
assert(!isa<ParamDecl>(VD) && "ParamDecl has a PatternBindingDecl?");

lib/AST/ASTWalker.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,19 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
171171
singleVar->getOriginalWrappedProperty() != nullptr;
172172
}
173173

174-
unsigned idx = 0U-1;
175-
for (auto entry : PBD->getPatternList()) {
176-
++idx;
177-
if (Pattern *Pat = doIt(entry.getPattern()))
178-
PBD->setPattern(idx, Pat, entry.getInitContext());
174+
for (auto idx : range(PBD->getNumPatternEntries())) {
175+
if (Pattern *Pat = doIt(PBD->getPattern(idx)))
176+
PBD->setPattern(idx, Pat, PBD->getInitContext(idx));
179177
else
180178
return true;
181-
if (entry.getInit() &&
179+
if (PBD->getInit(idx) &&
182180
!isPropertyWrapperBackingProperty &&
183-
(!entry.isInitializerSubsumed() ||
181+
(!PBD->isInitializerSubsumed(idx) ||
184182
Walker.shouldWalkIntoLazyInitializers())) {
185183
#ifndef NDEBUG
186184
PrettyStackTraceDecl debugStack("walking into initializer for", PBD);
187185
#endif
188-
if (Expr *E2 = doIt(entry.getInit()))
186+
if (Expr *E2 = doIt(PBD->getInit(idx)))
189187
PBD->setInit(idx, E2);
190188
else
191189
return true;

0 commit comments

Comments
 (0)