mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[AST] Separate the DeclContexts for different pattern binding entries in a pattern binding decl.
This commit is contained in:
@@ -494,16 +494,19 @@ public:
|
|||||||
/// deserialization.
|
/// deserialization.
|
||||||
class SerializedLocalDeclContext : public DeclContext {
|
class SerializedLocalDeclContext : public DeclContext {
|
||||||
private:
|
private:
|
||||||
const LocalDeclContextKind LocalKind;
|
unsigned LocalKind : 3;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
unsigned SpareBits : 29;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SerializedLocalDeclContext(LocalDeclContextKind LocalKind,
|
SerializedLocalDeclContext(LocalDeclContextKind LocalKind,
|
||||||
DeclContext *Parent)
|
DeclContext *Parent)
|
||||||
: DeclContext(DeclContextKind::SerializedLocal, Parent),
|
: DeclContext(DeclContextKind::SerializedLocal, Parent),
|
||||||
LocalKind(LocalKind) {}
|
LocalKind(static_cast<unsigned>(LocalKind)) {}
|
||||||
|
|
||||||
LocalDeclContextKind getLocalDeclContextKind() const {
|
LocalDeclContextKind getLocalDeclContextKind() const {
|
||||||
return LocalKind;
|
return static_cast<LocalDeclContextKind>(LocalKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const DeclContext *DC) {
|
static bool classof(const DeclContext *DC) {
|
||||||
|
|||||||
@@ -80,16 +80,20 @@ public:
|
|||||||
explicit PatternBindingInitializer(DeclContext *parent)
|
explicit PatternBindingInitializer(DeclContext *parent)
|
||||||
: Initializer(InitializerKind::PatternBinding, parent),
|
: Initializer(InitializerKind::PatternBinding, parent),
|
||||||
Binding(nullptr) {
|
Binding(nullptr) {
|
||||||
|
SpareBits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setBinding(PatternBindingDecl *binding) {
|
void setBinding(PatternBindingDecl *binding, unsigned bindingIndex) {
|
||||||
setParent(binding->getDeclContext());
|
setParent(binding->getDeclContext());
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
|
SpareBits = bindingIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternBindingDecl *getBinding() const { return Binding; }
|
PatternBindingDecl *getBinding() const { return Binding; }
|
||||||
|
|
||||||
|
unsigned getBindingIndex() const { return SpareBits; }
|
||||||
|
|
||||||
static bool classof(const DeclContext *DC) {
|
static bool classof(const DeclContext *DC) {
|
||||||
if (auto init = dyn_cast<Initializer>(DC))
|
if (auto init = dyn_cast<Initializer>(DC))
|
||||||
return classof(init);
|
return classof(init);
|
||||||
@@ -108,15 +112,21 @@ class SerializedPatternBindingInitializer : public SerializedLocalDeclContext {
|
|||||||
PatternBindingDecl *Binding;
|
PatternBindingDecl *Binding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SerializedPatternBindingInitializer(PatternBindingDecl *Binding)
|
SerializedPatternBindingInitializer(PatternBindingDecl *Binding,
|
||||||
|
unsigned bindingIndex)
|
||||||
: SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer,
|
: SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer,
|
||||||
Binding->getDeclContext()),
|
Binding->getDeclContext()),
|
||||||
Binding(Binding) {}
|
Binding(Binding) {
|
||||||
|
SpareBits = bindingIndex;
|
||||||
|
}
|
||||||
|
|
||||||
PatternBindingDecl *getBinding() const {
|
PatternBindingDecl *getBinding() const {
|
||||||
return Binding;
|
return Binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned getBindingIndex() const { return SpareBits; }
|
||||||
|
|
||||||
|
|
||||||
static bool classof(const DeclContext *DC) {
|
static bool classof(const DeclContext *DC) {
|
||||||
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
|
if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
|
||||||
return LDC->getLocalDeclContextKind() ==
|
return LDC->getLocalDeclContextKind() ==
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
|
|||||||
/// in source control, you should also update the comment to briefly
|
/// in source control, you should also update the comment to briefly
|
||||||
/// describe what change you made. The content of this comment isn't important;
|
/// describe what change you made. The content of this comment isn't important;
|
||||||
/// it just ensures a conflict if two people change the module format.
|
/// it just ensures a conflict if two people change the module format.
|
||||||
const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes
|
const uint16_t VERSION_MINOR = 265; // Last change: pattern binding initializer index
|
||||||
|
|
||||||
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
||||||
using DeclIDField = BCFixed<31>;
|
using DeclIDField = BCFixed<31>;
|
||||||
@@ -1306,7 +1306,8 @@ namespace decls_block {
|
|||||||
|
|
||||||
using PatternBindingInitializerLayout = BCRecordLayout<
|
using PatternBindingInitializerLayout = BCRecordLayout<
|
||||||
PATTERN_BINDING_INITIALIZER_CONTEXT,
|
PATTERN_BINDING_INITIALIZER_CONTEXT,
|
||||||
DeclIDField // parent pattern binding decl
|
DeclIDField, // parent pattern binding decl
|
||||||
|
BCVBR<3> // binding index in the pattern binding decl
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using DefaultArgumentInitializerLayout = BCRecordLayout<
|
using DefaultArgumentInitializerLayout = BCRecordLayout<
|
||||||
|
|||||||
@@ -722,7 +722,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
|
|||||||
switch (cast<Initializer>(this)->getInitializerKind()) {
|
switch (cast<Initializer>(this)->getInitializerKind()) {
|
||||||
case InitializerKind::PatternBinding: {
|
case InitializerKind::PatternBinding: {
|
||||||
auto init = cast<PatternBindingInitializer>(this);
|
auto init = cast<PatternBindingInitializer>(this);
|
||||||
OS << " PatternBinding 0x" << (void*) init->getBinding();
|
OS << " PatternBinding 0x" << (void*) init->getBinding()
|
||||||
|
<< " #" << init->getBindingIndex();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case InitializerKind::DefaultArgument: {
|
case InitializerKind::DefaultArgument: {
|
||||||
@@ -748,7 +749,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const {
|
|||||||
}
|
}
|
||||||
case LocalDeclContextKind::PatternBindingInitializer: {
|
case LocalDeclContextKind::PatternBindingInitializer: {
|
||||||
auto init = cast<SerializedPatternBindingInitializer>(local);
|
auto init = cast<SerializedPatternBindingInitializer>(local);
|
||||||
OS << " PatternBinding 0x" << (void*) init->getBinding();
|
OS << " PatternBinding 0x" << (void*) init->getBinding()
|
||||||
|
<< " #" << init->getBindingIndex();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LocalDeclContextKind::TopLevelCodeDecl:
|
case LocalDeclContextKind::TopLevelCodeDecl:
|
||||||
|
|||||||
@@ -3965,12 +3965,6 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
topLevelDecl = new (Context) TopLevelCodeDecl(CurDeclContext);
|
topLevelDecl = new (Context) TopLevelCodeDecl(CurDeclContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're not in a local context, we'll need a context to parse initializers
|
|
||||||
// into (should we have one). This happens for properties and global
|
|
||||||
// variables in libraries.
|
|
||||||
PatternBindingInitializer *initContext = nullptr;
|
|
||||||
bool usedInitContext = false;
|
|
||||||
|
|
||||||
bool HasAccessors = false; // Syntactically has accessor {}'s.
|
bool HasAccessors = false; // Syntactically has accessor {}'s.
|
||||||
ParserStatus Status;
|
ParserStatus Status;
|
||||||
|
|
||||||
@@ -3980,6 +3974,10 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// so we can build our singular PatternBindingDecl at the end.
|
// so we can build our singular PatternBindingDecl at the end.
|
||||||
SmallVector<PatternBindingEntry, 4> PBDEntries;
|
SmallVector<PatternBindingEntry, 4> PBDEntries;
|
||||||
|
|
||||||
|
// The pattern binding initializer contexts, which have to be set up at the
|
||||||
|
// end.
|
||||||
|
SmallVector<PatternBindingInitializer *, 4> PBDInitContexts;
|
||||||
|
|
||||||
// No matter what error path we take, make sure the
|
// No matter what error path we take, make sure the
|
||||||
// PatternBindingDecl/TopLevel code block are added.
|
// PatternBindingDecl/TopLevel code block are added.
|
||||||
SWIFT_DEFER {
|
SWIFT_DEFER {
|
||||||
@@ -3992,13 +3990,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// pattern/initializer pairs.
|
// pattern/initializer pairs.
|
||||||
auto PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling,
|
auto PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling,
|
||||||
VarLoc, PBDEntries, CurDeclContext);
|
VarLoc, PBDEntries, CurDeclContext);
|
||||||
|
|
||||||
|
// Wire up any initializer contexts we needed.
|
||||||
|
assert(PBDInitContexts.size() == PBDEntries.size());
|
||||||
|
for (unsigned i : indices(PBDInitContexts)) {
|
||||||
|
auto initContext = PBDInitContexts[i];
|
||||||
|
if (initContext) initContext->setBinding(PBD, i);
|
||||||
|
}
|
||||||
|
|
||||||
// If we're setting up a TopLevelCodeDecl, configure it by setting up the
|
// If we're setting up a TopLevelCodeDecl, configure it by setting up the
|
||||||
// body that holds PBD and we're done. The TopLevelCodeDecl is already set
|
// body that holds PBD and we're done. The TopLevelCodeDecl is already set
|
||||||
// up in Decls to be returned to caller.
|
// up in Decls to be returned to caller.
|
||||||
if (topLevelDecl) {
|
if (topLevelDecl) {
|
||||||
assert(!initContext &&
|
|
||||||
"Shouldn't need an initcontext: TopLevelCode is a local context!");
|
|
||||||
PBD->setDeclContext(topLevelDecl);
|
PBD->setDeclContext(topLevelDecl);
|
||||||
auto range = PBD->getSourceRange();
|
auto range = PBD->getSourceRange();
|
||||||
topLevelDecl->setBody(BraceStmt::create(Context, range.Start,
|
topLevelDecl->setBody(BraceStmt::create(Context, range.Start,
|
||||||
@@ -4006,18 +4009,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
Decls.insert(Decls.begin()+NumDeclsInResult, topLevelDecl);
|
Decls.insert(Decls.begin()+NumDeclsInResult, topLevelDecl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we set up an initialization context for a property or module-level
|
|
||||||
// global, check to see if we needed it and wind it down.
|
|
||||||
if (initContext) {
|
|
||||||
// If we didn't need the context, "destroy" it, which recycles it for
|
|
||||||
// the next user.
|
|
||||||
if (!usedInitContext)
|
|
||||||
Context.destroyPatternBindingContext(initContext);
|
|
||||||
else
|
|
||||||
initContext->setBinding(PBD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise return the PBD in "Decls" to the caller. We add it at a
|
// Otherwise return the PBD in "Decls" to the caller. We add it at a
|
||||||
// specific spot to get it in before any accessors, which SILGen seems to
|
// specific spot to get it in before any accessors, which SILGen seems to
|
||||||
// want.
|
// want.
|
||||||
@@ -4050,11 +4042,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// Remember this pattern/init pair for our ultimate PatternBindingDecl. The
|
// Remember this pattern/init pair for our ultimate PatternBindingDecl. The
|
||||||
// Initializer will be added later when/if it is parsed.
|
// Initializer will be added later when/if it is parsed.
|
||||||
PBDEntries.push_back({pattern, nullptr});
|
PBDEntries.push_back({pattern, nullptr});
|
||||||
|
PBDInitContexts.push_back(nullptr);
|
||||||
|
|
||||||
Expr *PatternInit = nullptr;
|
Expr *PatternInit = nullptr;
|
||||||
|
|
||||||
// Parse an initializer if present.
|
// Parse an initializer if present.
|
||||||
if (Tok.is(tok::equal)) {
|
if (Tok.is(tok::equal)) {
|
||||||
|
// If we're not in a local context, we'll need a context to parse initializers
|
||||||
|
// into (should we have one). This happens for properties and global
|
||||||
|
// variables in libraries.
|
||||||
|
PatternBindingInitializer *initContext = nullptr;
|
||||||
|
bool usedInitContext = false;
|
||||||
|
|
||||||
// Record the variables that we're trying to initialize. This allows us
|
// Record the variables that we're trying to initialize. This allows us
|
||||||
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
||||||
// decl (even though names aren't injected into scope when the initializer
|
// decl (even though names aren't injected into scope when the initializer
|
||||||
@@ -4114,7 +4113,18 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// we'll need to keep the initContext around.
|
// we'll need to keep the initContext around.
|
||||||
if (initContext)
|
if (initContext)
|
||||||
usedInitContext |= initParser->hasClosures();
|
usedInitContext |= initParser->hasClosures();
|
||||||
|
|
||||||
|
// If we set up an initialization context for a property or module-level
|
||||||
|
// global, check to see if we needed it and wind it down.
|
||||||
|
if (initContext) {
|
||||||
|
// If we didn't need the context, "destroy" it, which recycles it for
|
||||||
|
// the next user.
|
||||||
|
if (!usedInitContext)
|
||||||
|
Context.destroyPatternBindingContext(initContext);
|
||||||
|
else
|
||||||
|
PBDInitContexts.back() = initContext;
|
||||||
|
}
|
||||||
|
|
||||||
// If we are doing second pass of code completion, we don't want to
|
// If we are doing second pass of code completion, we don't want to
|
||||||
// suddenly cut off parsing and throw away the declaration.
|
// suddenly cut off parsing and throw away the declaration.
|
||||||
if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
|
if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) {
|
||||||
@@ -4144,6 +4154,12 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
// FIXME: Handle generalized parameters.
|
// FIXME: Handle generalized parameters.
|
||||||
Expr *paramExpr = nullptr;
|
Expr *paramExpr = nullptr;
|
||||||
if (Tok.is(tok::l_brace)) {
|
if (Tok.is(tok::l_brace)) {
|
||||||
|
// If we're not in a local context, we'll need a context to parse initializers
|
||||||
|
// into (should we have one). This happens for properties and global
|
||||||
|
// variables in libraries.
|
||||||
|
PatternBindingInitializer *initContext = nullptr;
|
||||||
|
bool usedInitContext = false;
|
||||||
|
|
||||||
// Record the variables that we're trying to set up. This allows us
|
// Record the variables that we're trying to set up. This allows us
|
||||||
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
// to cleanly reject "var x = x" when "x" isn't bound to an enclosing
|
||||||
// decl (even though names aren't injected into scope when the parameter
|
// decl (even though names aren't injected into scope when the parameter
|
||||||
@@ -4172,7 +4188,11 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags,
|
|||||||
initParser.emplace(*this, initContext);
|
initParser.emplace(*this, initContext);
|
||||||
|
|
||||||
auto closure = parseExprClosure();
|
auto closure = parseExprClosure();
|
||||||
usedInitContext = true;
|
if (initContext) {
|
||||||
|
usedInitContext = true;
|
||||||
|
PBDInitContexts.back() = initContext;
|
||||||
|
}
|
||||||
|
|
||||||
if (closure.isParseError())
|
if (closure.isParseError())
|
||||||
return makeParserError();
|
return makeParserError();
|
||||||
if (closure.hasCodeCompletion())
|
if (closure.hasCodeCompletion())
|
||||||
|
|||||||
@@ -1930,7 +1930,7 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
|
|||||||
// If we didn't find one, create it.
|
// If we didn't find one, create it.
|
||||||
if (!initContext) {
|
if (!initContext) {
|
||||||
initContext = Context.createPatternBindingContext(DC);
|
initContext = Context.createPatternBindingContext(DC);
|
||||||
initContext->setBinding(PBD);
|
initContext->setBinding(PBD, patternNumber);
|
||||||
initContextIsNew = true;
|
initContextIsNew = true;
|
||||||
}
|
}
|
||||||
DC = initContext;
|
DC = initContext;
|
||||||
|
|||||||
@@ -1507,13 +1507,15 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) {
|
|||||||
|
|
||||||
case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
|
case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: {
|
||||||
DeclID bindingID;
|
DeclID bindingID;
|
||||||
|
uint32_t bindingIndex;
|
||||||
decls_block::PatternBindingInitializerLayout::readRecord(scratch,
|
decls_block::PatternBindingInitializerLayout::readRecord(scratch,
|
||||||
bindingID);
|
bindingID,
|
||||||
|
bindingIndex);
|
||||||
auto decl = getDecl(bindingID);
|
auto decl = getDecl(bindingID);
|
||||||
PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);
|
PatternBindingDecl *binding = cast<PatternBindingDecl>(decl);
|
||||||
|
|
||||||
declContextOrOffset = new (ctx)
|
declContextOrOffset = new (ctx)
|
||||||
SerializedPatternBindingInitializer(binding);
|
SerializedPatternBindingInitializer(binding, bindingIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1845,11 +1845,13 @@ void Serializer::writeDeclContext(const DeclContext *DC) {
|
|||||||
declOrDeclContextID, isDecl);
|
declOrDeclContextID, isDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding) {
|
void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding,
|
||||||
|
unsigned bindingIndex) {
|
||||||
using namespace decls_block;
|
using namespace decls_block;
|
||||||
auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];
|
auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code];
|
||||||
PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
|
PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord,
|
||||||
abbrCode, addDeclRef(binding));
|
abbrCode, addDeclRef(binding),
|
||||||
|
bindingIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1896,7 +1898,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
|
|||||||
|
|
||||||
case DeclContextKind::Initializer: {
|
case DeclContextKind::Initializer: {
|
||||||
if (auto PBI = dyn_cast<PatternBindingInitializer>(DC)) {
|
if (auto PBI = dyn_cast<PatternBindingInitializer>(DC)) {
|
||||||
writePatternBindingInitializer(PBI->getBinding());
|
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
|
||||||
} else if (auto DAI = dyn_cast<DefaultArgumentInitializer>(DC)) {
|
} else if (auto DAI = dyn_cast<DefaultArgumentInitializer>(DC)) {
|
||||||
writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
|
writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex());
|
||||||
}
|
}
|
||||||
@@ -1928,7 +1930,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) {
|
|||||||
}
|
}
|
||||||
case LocalDeclContextKind::PatternBindingInitializer: {
|
case LocalDeclContextKind::PatternBindingInitializer: {
|
||||||
auto PBI = cast<SerializedPatternBindingInitializer>(local);
|
auto PBI = cast<SerializedPatternBindingInitializer>(local);
|
||||||
writePatternBindingInitializer(PBI->getBinding());
|
writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case LocalDeclContextKind::TopLevelCodeDecl: {
|
case LocalDeclContextKind::TopLevelCodeDecl: {
|
||||||
|
|||||||
@@ -293,7 +293,8 @@ private:
|
|||||||
void writeLocalDeclContext(const DeclContext *DC);
|
void writeLocalDeclContext(const DeclContext *DC);
|
||||||
|
|
||||||
/// Write the components of a PatternBindingInitializer as a local context.
|
/// Write the components of a PatternBindingInitializer as a local context.
|
||||||
void writePatternBindingInitializer(PatternBindingDecl *binding);
|
void writePatternBindingInitializer(PatternBindingDecl *binding,
|
||||||
|
unsigned bindingIndex);
|
||||||
|
|
||||||
/// Write the components of a DefaultArgumentInitializer as a local context.
|
/// Write the components of a DefaultArgumentInitializer as a local context.
|
||||||
void writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index);
|
void writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index);
|
||||||
|
|||||||
Reference in New Issue
Block a user