Skip to content

Commit 5e25d25

Browse files
committed
[AST] Separate the DeclContexts for different pattern binding entries in a pattern binding decl.
1 parent 4a24b06 commit 5e25d25

File tree

9 files changed

+83
-42
lines changed

9 files changed

+83
-42
lines changed

include/swift/AST/DeclContext.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,16 +494,19 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
494494
/// deserialization.
495495
class SerializedLocalDeclContext : public DeclContext {
496496
private:
497-
const LocalDeclContextKind LocalKind;
497+
unsigned LocalKind : 3;
498+
499+
protected:
500+
unsigned SpareBits : 29;
498501

499502
public:
500503
SerializedLocalDeclContext(LocalDeclContextKind LocalKind,
501504
DeclContext *Parent)
502505
: DeclContext(DeclContextKind::SerializedLocal, Parent),
503-
LocalKind(LocalKind) {}
506+
LocalKind(static_cast<unsigned>(LocalKind)) {}
504507

505508
LocalDeclContextKind getLocalDeclContextKind() const {
506-
return LocalKind;
509+
return static_cast<LocalDeclContextKind>(LocalKind);
507510
}
508511

509512
static bool classof(const DeclContext *DC) {

include/swift/AST/Initializer.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,20 @@ class PatternBindingInitializer : public Initializer {
8080
explicit PatternBindingInitializer(DeclContext *parent)
8181
: Initializer(InitializerKind::PatternBinding, parent),
8282
Binding(nullptr) {
83+
SpareBits = 0;
8384
}
8485

8586

86-
void setBinding(PatternBindingDecl *binding) {
87+
void setBinding(PatternBindingDecl *binding, unsigned bindingIndex) {
8788
setParent(binding->getDeclContext());
8889
Binding = binding;
90+
SpareBits = bindingIndex;
8991
}
9092

9193
PatternBindingDecl *getBinding() const { return Binding; }
9294

95+
unsigned getBindingIndex() const { return SpareBits; }
96+
9397
static bool classof(const DeclContext *DC) {
9498
if (auto init = dyn_cast<Initializer>(DC))
9599
return classof(init);
@@ -108,15 +112,21 @@ class SerializedPatternBindingInitializer : public SerializedLocalDeclContext {
108112
PatternBindingDecl *Binding;
109113

110114
public:
111-
SerializedPatternBindingInitializer(PatternBindingDecl *Binding)
115+
SerializedPatternBindingInitializer(PatternBindingDecl *Binding,
116+
unsigned bindingIndex)
112117
: SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer,
113118
Binding->getDeclContext()),
114-
Binding(Binding) {}
119+
Binding(Binding) {
120+
SpareBits = bindingIndex;
121+
}
115122

116123
PatternBindingDecl *getBinding() const {
117124
return Binding;
118125
}
119126

127+
unsigned getBindingIndex() const { return SpareBits; }
128+
129+
120130
static bool classof(const DeclContext *DC) {
121131
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
122132
return LDC->getLocalDeclContextKind() ==

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes
56+
const uint16_t VERSION_MINOR = 265; // Last change: pattern binding initializer index
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;
@@ -1306,7 +1306,8 @@ namespace decls_block {
13061306

13071307
using PatternBindingInitializerLayout = BCRecordLayout<
13081308
PATTERN_BINDING_INITIALIZER_CONTEXT,
1309-
DeclIDField // parent pattern binding decl
1309+
DeclIDField, // parent pattern binding decl
1310+
BCVBR<3> // binding index in the pattern binding decl
13101311
>;
13111312

13121313
using DefaultArgumentInitializerLayout = BCRecordLayout<

lib/AST/DeclContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
722722
switch (cast<Initializer>(this)->getInitializerKind()) {
723723
case InitializerKind::PatternBinding: {
724724
auto init = cast<PatternBindingInitializer>(this);
725-
OS << " PatternBinding 0x" << (void*) init->getBinding();
725+
OS << " PatternBinding 0x" << (void*) init->getBinding()
726+
<< " #" << init->getBindingIndex();
726727
break;
727728
}
728729
case InitializerKind::DefaultArgument: {
@@ -748,7 +749,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
748749
}
749750
case LocalDeclContextKind::PatternBindingInitializer: {
750751
auto init = cast<SerializedPatternBindingInitializer>(local);
751-
OS << " PatternBinding 0x" << (void*) init->getBinding();
752+
OS << " PatternBinding 0x" << (void*) init->getBinding()
753+
<< " #" << init->getBindingIndex();
752754
break;
753755
}
754756
case LocalDeclContextKind::TopLevelCodeDecl:

lib/Parse/ParseDecl.cpp

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3965,12 +3965,6 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
39653965
topLevelDecl = new (Context) TopLevelCodeDecl(CurDeclContext);
39663966
}
39673967

3968-
// If we're not in a local context, we'll need a context to parse initializers
3969-
// into (should we have one). This happens for properties and global
3970-
// variables in libraries.
3971-
PatternBindingInitializer *initContext = nullptr;
3972-
bool usedInitContext = false;
3973-
39743968
bool HasAccessors = false; // Syntactically has accessor {}'s.
39753969
ParserStatus Status;
39763970

@@ -3980,6 +3974,10 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
39803974
// so we can build our singular PatternBindingDecl at the end.
39813975
SmallVector<PatternBindingEntry, 4> PBDEntries;
39823976

3977+
// The pattern binding initializer contexts, which have to be set up at the
3978+
// end.
3979+
SmallVector<PatternBindingInitializer *, 4> PBDInitContexts;
3980+
39833981
// No matter what error path we take, make sure the
39843982
// PatternBindingDecl/TopLevel code block are added.
39853983
SWIFT_DEFER {
@@ -3992,32 +3990,26 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
39923990
// pattern/initializer pairs.
39933991
auto PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling,
39943992
VarLoc, PBDEntries, CurDeclContext);
3995-
3993+
3994+
// Wire up any initializer contexts we needed.
3995+
assert(PBDInitContexts.size() == PBDEntries.size());
3996+
for (unsigned i : indices(PBDInitContexts)) {
3997+
auto initContext = PBDInitContexts[i];
3998+
if (initContext) initContext->setBinding(PBD, i);
3999+
}
4000+
39964001
// If we're setting up a TopLevelCodeDecl, configure it by setting up the
39974002
// body that holds PBD and we're done. The TopLevelCodeDecl is already set
39984003
// up in Decls to be returned to caller.
39994004
if (topLevelDecl) {
4000-
assert(!initContext &&
4001-
"Shouldn't need an initcontext: TopLevelCode is a local context!");
40024005
PBD->setDeclContext(topLevelDecl);
40034006
auto range = PBD->getSourceRange();
40044007
topLevelDecl->setBody(BraceStmt::create(Context, range.Start,
40054008
ASTNode(PBD), range.End, true));
40064009
Decls.insert(Decls.begin()+NumDeclsInResult, topLevelDecl);
40074010
return;
40084011
}
4009-
4010-
// If we set up an initialization context for a property or module-level
4011-
// global, check to see if we needed it and wind it down.
4012-
if (initContext) {
4013-
// If we didn't need the context, "destroy" it, which recycles it for
4014-
// the next user.
4015-
if (!usedInitContext)
4016-
Context.destroyPatternBindingContext(initContext);
4017-
else
4018-
initContext->setBinding(PBD);
4019-
}
4020-
4012+
40214013
// Otherwise return the PBD in "Decls" to the caller. We add it at a
40224014
// specific spot to get it in before any accessors, which SILGen seems to
40234015
// want.
@@ -4050,11 +4042,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
40504042
// Remember this pattern/init pair for our ultimate PatternBindingDecl. The
40514043
// Initializer will be added later when/if it is parsed.
40524044
PBDEntries.push_back({pattern, nullptr});
4053-
4045+
PBDInitContexts.push_back(nullptr);
4046+
40544047
Expr *PatternInit = nullptr;
40554048

40564049
// Parse an initializer if present.
40574050
if (Tok.is(tok::equal)) {
4051+
// If we're not in a local context, we'll need a context to parse initializers
4052+
// into (should we have one). This happens for properties and global
4053+
// variables in libraries.
4054+
PatternBindingInitializer *initContext = nullptr;
4055+
bool usedInitContext = false;
4056+
40584057
// Record the variables that we're trying to initialize. This allows us
40594058
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
40604059
// decl (even though names aren't injected into scope when the initializer
@@ -4114,7 +4113,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
41144113
// we'll need to keep the initContext around.
41154114
if (initContext)
41164115
usedInitContext |= initParser->hasClosures();
4117-
4116+
4117+
// If we set up an initialization context for a property or module-level
4118+
// global, check to see if we needed it and wind it down.
4119+
if (initContext) {
4120+
// If we didn't need the context, "destroy" it, which recycles it for
4121+
// the next user.
4122+
if (!usedInitContext)
4123+
Context.destroyPatternBindingContext(initContext);
4124+
else
4125+
PBDInitContexts.back() = initContext;
4126+
}
4127+
41184128
// If we are doing second pass of code completion, we don't want to
41194129
// suddenly cut off parsing and throw away the declaration.
41204130
if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
@@ -4144,6 +4154,12 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
41444154
// FIXME: Handle generalized parameters.
41454155
Expr *paramExpr = nullptr;
41464156
if (Tok.is(tok::l_brace)) {
4157+
// If we're not in a local context, we'll need a context to parse initializers
4158+
// into (should we have one). This happens for properties and global
4159+
// variables in libraries.
4160+
PatternBindingInitializer *initContext = nullptr;
4161+
bool usedInitContext = false;
4162+
41474163
// Record the variables that we're trying to set up. This allows us
41484164
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
41494165
// decl (even though names aren't injected into scope when the parameter
@@ -4172,7 +4188,11 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
41724188
initParser.emplace(*this, initContext);
41734189

41744190
auto closure = parseExprClosure();
4175-
usedInitContext = true;
4191+
if (initContext) {
4192+
usedInitContext = true;
4193+
PBDInitContexts.back() = initContext;
4194+
}
4195+
41764196
if (closure.isParseError())
41774197
return makeParserError();
41784198
if (closure.hasCodeCompletion())

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1930,7 +1930,7 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
19301930
// If we didn't find one, create it.
19311931
if (!initContext) {
19321932
initContext = Context.createPatternBindingContext(DC);
1933-
initContext->setBinding(PBD);
1933+
initContext->setBinding(PBD, patternNumber);
19341934
initContextIsNew = true;
19351935
}
19361936
DC = initContext;

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,13 +1507,15 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
15071507

15081508
case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
15091509
DeclID bindingID;
1510+
uint32_t bindingIndex;
15101511
decls_block::PatternBindingInitializerLayout::readRecord(scratch,
1511-
bindingID);
1512+
bindingID,
1513+
bindingIndex);
15121514
auto decl = getDecl(bindingID);
15131515
PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);
15141516

15151517
declContextOrOffset = new (ctx)
1516-
SerializedPatternBindingInitializer(binding);
1518+
SerializedPatternBindingInitializer(binding, bindingIndex);
15171519
break;
15181520
}
15191521

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,11 +1845,13 @@ void Serializer::writeDeclContext(const DeclContext *DC) {
18451845
declOrDeclContextID, isDecl);
18461846
}
18471847

1848-
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding) {
1848+
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding,
1849+
unsigned bindingIndex) {
18491850
using namespace decls_block;
18501851
auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];
18511852
PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
1852-
abbrCode, addDeclRef(binding));
1853+
abbrCode, addDeclRef(binding),
1854+
bindingIndex);
18531855
}
18541856

18551857
void
@@ -1896,7 +1898,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
18961898

18971899
case DeclContextKind::Initializer: {
18981900
if (auto PBI = dyn_cast<PatternBindingInitializer>(DC)) {
1899-
writePatternBindingInitializer(PBI->getBinding());
1901+
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
19001902
} else if (auto DAI = dyn_cast<DefaultArgumentInitializer>(DC)) {
19011903
writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
19021904
}
@@ -1928,7 +1930,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
19281930
}
19291931
case LocalDeclContextKind::PatternBindingInitializer: {
19301932
auto PBI = cast<SerializedPatternBindingInitializer>(local);
1931-
writePatternBindingInitializer(PBI->getBinding());
1933+
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
19321934
return;
19331935
}
19341936
case LocalDeclContextKind::TopLevelCodeDecl: {

lib/Serialization/Serialization.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ class Serializer {
293293
void writeLocalDeclContext(const DeclContext *DC);
294294

295295
/// Write the components of a PatternBindingInitializer as a local context.
296-
void writePatternBindingInitializer(PatternBindingDecl *binding);
296+
void writePatternBindingInitializer(PatternBindingDecl *binding,
297+
unsigned bindingIndex);
297298

298299
/// Write the components of a DefaultArgumentInitializer as a local context.
299300
void writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index);

0 commit comments

Comments
 (0)