diff --git a/include/swift/AST/AST.h b/include/swift/AST/AST.h index 283ceb1e7d7d4..a7c37cea34792 100644 --- a/include/swift/AST/AST.h +++ b/include/swift/AST/AST.h @@ -22,7 +22,6 @@ #include "swift/AST/Builtins.h" #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/Initializer.h" #include "swift/AST/Module.h" #include "swift/AST/ParameterList.h" diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index dc3f256f085ab..97b87a981cb53 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -549,21 +549,6 @@ class ASTContext { addCleanup([&object]{ object.~T(); }); } - /// Create a context for the initializer of a non-local variable, - /// like a global or a field. To reduce memory usage, if the - /// context goes unused, it should be returned to the ASTContext - /// with destroyPatternBindingContext. - PatternBindingInitializer *createPatternBindingContext(DeclContext *parent); - void destroyPatternBindingContext(PatternBindingInitializer *DC); - - /// Create a context for the initializer of the nth default argument - /// of the given function. To reduce memory usage, if the context - /// goes unused, it should be returned to the ASTContext with - /// destroyDefaultArgumentContext. - DefaultArgumentInitializer *createDefaultArgumentContext(DeclContext *fn, - unsigned index); - void destroyDefaultArgumentContext(DefaultArgumentInitializer *DC); - //===--------------------------------------------------------------------===// // Diagnostics Helper functions //===--------------------------------------------------------------------===// diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index e1512f05f8922..fa9ec94c9fcfc 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -21,7 +21,6 @@ #include "swift/AST/ClangNode.h" #include "swift/AST/ConcreteDeclRef.h" #include "swift/AST/DefaultArgumentKind.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/TypeAlignments.h" @@ -246,8 +245,11 @@ class alignas(1 << DeclAlignInBits) Decl { /// \brief Whether 'static' or 'class' was used. unsigned StaticSpelling : 2; + + /// \brief The number of pattern binding declarations. + unsigned NumPatternEntries : 16; }; - enum { NumPatternBindingDeclBits = NumDeclBits + 3 }; + enum { NumPatternBindingDeclBits = NumDeclBits + 19 }; static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned"); class ValueDeclBitfields { @@ -1668,9 +1670,14 @@ class PatternBindingEntry { // initializer is ASTContext-allocated it is safe. llvm::PointerIntPair> InitCheckedAndRemoved; + /// The initializer context used for this pattern binding entry. + DeclContext *InitContext = nullptr; + + friend class PatternBindingInitializer; + public: - PatternBindingEntry(Pattern *P, Expr *E) - : ThePattern(P), InitCheckedAndRemoved(E, {}) {} + PatternBindingEntry(Pattern *P, Expr *E, DeclContext *InitContext) + : ThePattern(P), InitCheckedAndRemoved(E, {}), InitContext(InitContext) {} Pattern *getPattern() const { return ThePattern; } void setPattern(Pattern *P) { ThePattern = P; } @@ -1690,6 +1697,12 @@ class PatternBindingEntry { // Return the first variable initialized by this pattern. VarDecl *getAnchoringVarDecl() const; + + // Retrieve the declaration context for the intializer. + DeclContext *getInitContext() const { return InitContext; } + + /// Override the initializer context. + void setInitContext(DeclContext *dc) { InitContext = dc; } }; /// \brief This decl contains a pattern and optional initializer for a set @@ -1711,8 +1724,6 @@ class PatternBindingDecl final : public Decl, SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present. SourceLoc VarLoc; ///< Location of the 'var' keyword. - unsigned numPatternEntries; - friend class Decl; PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, @@ -1732,13 +1743,22 @@ class PatternBindingDecl final : public Decl, Pattern *Pat, Expr *E, DeclContext *Parent); + static PatternBindingDecl *createDeserialized( + ASTContext &Ctx, SourceLoc StaticLoc, + StaticSpellingKind StaticSpelling, + SourceLoc VarLoc, + unsigned NumPatternEntries, + DeclContext *Parent); + SourceLoc getStartLoc() const { return StaticLoc.isValid() ? StaticLoc : VarLoc; } SourceLoc getLoc() const { return VarLoc; } SourceRange getSourceRange() const; - unsigned getNumPatternEntries() const { return numPatternEntries; } + unsigned getNumPatternEntries() const { + return PatternBindingDeclBits.NumPatternEntries; + } ArrayRef getPatternList() const { return const_cast(this)->getMutablePatternList(); @@ -1760,7 +1780,7 @@ class PatternBindingDecl final : public Decl, return getPatternList()[i].getPattern(); } - void setPattern(unsigned i, Pattern *Pat); + void setPattern(unsigned i, Pattern *Pat, DeclContext *InitContext); /// Given that this PBD is the parent pattern for the specified VarDecl, /// return the entry of the VarDecl in our PatternList. For example, in: @@ -1810,7 +1830,7 @@ class PatternBindingDecl final : public Decl, private: MutableArrayRef getMutablePatternList() { // Pattern entries are tail allocated. - return {getTrailingObjects(), numPatternEntries}; + return {getTrailingObjects(), getNumPatternEntries()}; } }; @@ -4255,8 +4275,13 @@ class ParamDecl : public VarDecl { SourceLoc ArgumentNameLoc; SourceLoc LetVarInOutLoc; + struct StoredDefaultArgument { + Expr *DefaultArg = nullptr; + Initializer *InitContext = nullptr; + }; + /// The default value, if any, along with whether this is varargs. - llvm::PointerIntPair DefaultValueAndIsVariadic; + llvm::PointerIntPair DefaultValueAndIsVariadic; /// True if the type is implicitly specified in the source, but this has an /// apparently valid typeRepr. This is used in accessors, which look like: @@ -4302,13 +4327,22 @@ class ParamDecl : public VarDecl { defaultArgumentKind = K; } - void setDefaultValue(ExprHandle *H) { - DefaultValueAndIsVariadic.setPointer(H); + Expr *getDefaultValue() const { + if (auto stored = DefaultValueAndIsVariadic.getPointer()) + return stored->DefaultArg; + return nullptr; } - ExprHandle *getDefaultValue() const { - return DefaultValueAndIsVariadic.getPointer(); + + void setDefaultValue(Expr *E); + + Initializer *getDefaultArgumentInitContext() const { + if (auto stored = DefaultValueAndIsVariadic.getPointer()) + return stored->InitContext; + return nullptr; } + void setDefaultArgumentInitContext(Initializer *initContext); + /// Whether or not this parameter is varargs. bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); } void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);} diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index 0e8fee97fcab7..b6a948ed40aa3 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -494,16 +494,19 @@ class alignas(1 << DeclContextAlignInBits) DeclContext { /// deserialization. class SerializedLocalDeclContext : public DeclContext { private: - const LocalDeclContextKind LocalKind; + unsigned LocalKind : 3; + +protected: + unsigned SpareBits : 29; public: SerializedLocalDeclContext(LocalDeclContextKind LocalKind, DeclContext *Parent) : DeclContext(DeclContextKind::SerializedLocal, Parent), - LocalKind(LocalKind) {} + LocalKind(static_cast(LocalKind)) {} LocalDeclContextKind getLocalDeclContextKind() const { - return LocalKind; + return static_cast(LocalKind); } static bool classof(const DeclContext *DC) { diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 2b0abbb3f3db3..e7886025e0c1b 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -539,11 +539,6 @@ class alignas(8) Expr { /// walk into the body of it (unless it is single-expression). void forEachChildExpr(const std::function &callback); - /// findExistingInitializerContext - Given that this expression is - /// an initializer that belongs in some sort of Initializer - /// context, look through it for any existing context object. - Initializer *findExistingInitializerContext(); - /// Determine whether this expression refers to a type by name. /// /// This distinguishes static references to types, like Int, from metatype diff --git a/include/swift/AST/ExprHandle.h b/include/swift/AST/ExprHandle.h deleted file mode 100644 index 476a437beaefa..0000000000000 --- a/include/swift/AST/ExprHandle.h +++ /dev/null @@ -1,63 +0,0 @@ -//===--- ExprHandle.h - Swift Expression Handle -----------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// This file defines the ExprHandle class. -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_EXPRHANDLE_H -#define SWIFT_EXPRHANDLE_H - -#include "swift/AST/TypeAlignments.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/ADT/PointerIntPair.h" - -namespace swift { - class ASTContext; - class Expr; - -/// ExprHandle - Provides an indirection for expressions, so both a type and a -/// pattern can point at the same expression during type-checking. -class alignas(8) ExprHandle { - /// \brief The expression along with a bit saying whether this expression - /// was already type-checked (or not). - llvm::PointerIntPair EAndChecked; -private: - ExprHandle(Expr *E) : EAndChecked(E, false) {} - - void *operator new(size_t Bytes) throw() = delete; - void operator delete(void *Data) throw() = delete; - void *operator new(size_t Bytes, void *Mem) throw() = delete; - void *operator new(size_t Bytes, ASTContext &C, - unsigned Alignment = 8); -public: - Expr *getExpr() { - return EAndChecked.getPointer(); - } - - /// \brief Determine whether the referenced expression has already been - /// type-checked. - bool alreadyChecked() const { return EAndChecked.getInt(); } - - /// \brief Set the expression after it has been type-checked. - void setExpr(Expr *newE, bool checked) { - assert(newE && "Null expression in handle"); - EAndChecked.setPointer(newE); - EAndChecked.setInt(checked); - } - - static ExprHandle *get(ASTContext &Context, Expr *E); -}; - -} // end namespace swift - -#endif diff --git a/include/swift/AST/Initializer.h b/include/swift/AST/Initializer.h index f757c9525743f..3ce23cf22e29b 100644 --- a/include/swift/AST/Initializer.h +++ b/include/swift/AST/Initializer.h @@ -80,16 +80,20 @@ class PatternBindingInitializer : public Initializer { explicit PatternBindingInitializer(DeclContext *parent) : Initializer(InitializerKind::PatternBinding, parent), Binding(nullptr) { + SpareBits = 0; } - void setBinding(PatternBindingDecl *binding) { + void setBinding(PatternBindingDecl *binding, unsigned bindingIndex) { setParent(binding->getDeclContext()); Binding = binding; + SpareBits = bindingIndex; } PatternBindingDecl *getBinding() const { return Binding; } + unsigned getBindingIndex() const { return SpareBits; } + static bool classof(const DeclContext *DC) { if (auto init = dyn_cast(DC)) return classof(init); @@ -108,15 +112,21 @@ class SerializedPatternBindingInitializer : public SerializedLocalDeclContext { PatternBindingDecl *Binding; public: - SerializedPatternBindingInitializer(PatternBindingDecl *Binding) + SerializedPatternBindingInitializer(PatternBindingDecl *Binding, + unsigned bindingIndex) : SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer, Binding->getDeclContext()), - Binding(Binding) {} + Binding(Binding) { + SpareBits = bindingIndex; + } PatternBindingDecl *getBinding() const { return Binding; } + unsigned getBindingIndex() const { return SpareBits; } + + static bool classof(const DeclContext *DC) { if (auto LDC = dyn_cast(DC)) return LDC->getLocalDeclContextKind() == @@ -145,11 +155,8 @@ class DefaultArgumentInitializer : public Initializer { /// Change the parent of this context. This is necessary because /// the function signature is parsed before the function /// declaration/expression itself is built. - void changeFunction(DeclContext *parent) { - assert(parent->isLocalContext()); - setParent(parent); - } - + void changeFunction(AbstractFunctionDecl *parent); + static bool classof(const DeclContext *DC) { if (auto init = dyn_cast(DC)) return classof(init); diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index 039b0ce931728..03549815ef201 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -32,7 +32,6 @@ namespace swift { class DeclContext; class IdentTypeRepr; class ValueDecl; - class ExprHandle; class NamedTypeRepr; enum class TypeReprKind : uint8_t { diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 79f667097ae8a..e1198311934f6 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -42,7 +42,6 @@ namespace swift { class AssociatedTypeDecl; class ASTContext; class ClassDecl; - class ExprHandle; class GenericTypeParamDecl; class GenericTypeParamType; class GenericParamList; diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index a10057b9d4dd0..b47d8060a0ef0 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -924,7 +924,7 @@ class Parser { /// Set the parsed context for all the initializers to the given /// function. - void setFunctionContext(DeclContext *DC); + void setFunctionContext(AbstractFunctionDecl *AFD); DefaultArgumentInfo(bool inTypeContext) { NextIndex = inTypeContext ? 1 : 0; @@ -970,7 +970,7 @@ class Parser { TypeRepr *Type = nullptr; /// The default argument for this parameter. - ExprHandle *DefaultArg = nullptr; + Expr *DefaultArg = nullptr; /// True if we emitted a parse error about this parameter. bool isInvalid = false; diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 7c58975eb9471..875f31223fd36 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0; /// in source control, you should also update the comment to briefly /// 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. -const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes +const uint16_t VERSION_MINOR = 266; // Last change: pattern binding init contexts using DeclID = PointerEmbeddedInt; using DeclIDField = BCFixed<31>; @@ -927,9 +927,9 @@ namespace decls_block { BCFixed<1>, // implicit flag BCFixed<1>, // static? StaticSpellingKindField, // spelling of 'static' or 'class' - BCVBR<3> // numpatterns - - // The pattern trails the record. + BCVBR<3>, // numpatterns + BCArray // init contexts + // The patterns and decl-contexts trail the record. >; template @@ -1306,7 +1306,8 @@ namespace decls_block { using PatternBindingInitializerLayout = BCRecordLayout< 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< diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c702ee2df25a3..d031d6e789af5 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -22,7 +22,6 @@ #include "swift/AST/ConcreteDeclRef.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSema.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/KnownProtocols.h" @@ -259,12 +258,6 @@ struct ASTContext::Implementation { llvm::DenseMap> ConformanceLoaders; - /// \brief A cached unused pattern-binding initializer context. - PatternBindingInitializer *UnusedPatternBindingContext = nullptr; - - /// \brief A cached unused default-argument initializer context. - DefaultArgumentInitializer *UnusedDefaultArgumentContext = nullptr; - /// Mapping from archetypes with lazily-resolved nested types to the /// archetype builder and potential archetype corresponding to that /// archetype. @@ -1563,38 +1556,6 @@ void ValueDecl::setLocalDiscriminator(unsigned index) { getASTContext().Impl.LocalDiscriminators.insert({this, index}); } -PatternBindingInitializer * -ASTContext::createPatternBindingContext(DeclContext *parent) { - // Check for an existing context we can re-use. - if (auto existing = Impl.UnusedPatternBindingContext) { - Impl.UnusedPatternBindingContext = nullptr; - existing->reset(parent); - return existing; - } - - return new (*this) PatternBindingInitializer(parent); -} -void ASTContext::destroyPatternBindingContext(PatternBindingInitializer *DC) { - // There isn't much value in caching more than one of these. - Impl.UnusedPatternBindingContext = DC; -} - -DefaultArgumentInitializer * -ASTContext::createDefaultArgumentContext(DeclContext *fn, unsigned index) { - // Check for an existing context we can re-use. - if (auto existing = Impl.UnusedDefaultArgumentContext) { - Impl.UnusedDefaultArgumentContext = nullptr; - existing->reset(fn, index); - return existing; - } - - return new (*this) DefaultArgumentInitializer(fn, index); -} -void ASTContext::destroyDefaultArgumentContext(DefaultArgumentInitializer *DC) { - // There isn't much value in caching more than one of these. - Impl.UnusedDefaultArgumentContext = DC; -} - NormalProtocolConformance * ASTContext::getBehaviorConformance(Type conformingType, Type conformingInterfaceType, @@ -3682,15 +3643,6 @@ CanType ArchetypeType::getAnyOpened(Type existential) { return ArchetypeType::getOpened(existential); } -void *ExprHandle::operator new(size_t Bytes, ASTContext &C, - unsigned Alignment) { - return C.Allocate(Bytes, Alignment); -} - -ExprHandle *ExprHandle::get(ASTContext &Context, Expr *E) { - return new (Context) ExprHandle(E); -} - void TypeLoc::setInvalidType(ASTContext &C) { TAndValidBit.setPointerAndInt(ErrorType::get(C), true); } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 1ef7516c01319..07152c6c6aede 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -831,7 +831,7 @@ namespace { if (auto init = P->getDefaultValue()) { OS << " expression=\n"; - printRec(init->getExpr()); + printRec(init); } OS << ')'; diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index 24a3d92f90fa1..691597a26601b 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -55,7 +55,6 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/ASTVisitor.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/ParameterList.h" #include "swift/AST/PrettyStackTrace.h" using namespace swift; @@ -150,7 +149,7 @@ class Traversal : public ASTVisitorgetPatternList()) { ++idx; if (Pattern *Pat = doIt(entry.getPattern())) - PBD->setPattern(idx, Pat); + PBD->setPattern(idx, Pat, entry.getInitContext()); else return true; if (entry.getInit()) { @@ -899,9 +898,9 @@ class Traversal : public ASTVisitorgetDefaultValue()) { - auto res = doIt(E->getExpr()); + auto res = doIt(E); if (!res) return true; - E->setExpr(res, E->alreadyChecked()); + P->setDefaultValue(res); } } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index e10852799cd53..13c5d29ee9fd9 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -792,11 +792,11 @@ PatternBindingDecl::PatternBindingDecl(SourceLoc StaticLoc, unsigned NumPatternEntries, DeclContext *Parent) : Decl(DeclKind::PatternBinding, Parent), - StaticLoc(StaticLoc), VarLoc(VarLoc), - numPatternEntries(NumPatternEntries) { + StaticLoc(StaticLoc), VarLoc(VarLoc) { PatternBindingDeclBits.IsStatic = StaticLoc.isValid(); PatternBindingDeclBits.StaticSpelling = static_cast(StaticSpelling); + PatternBindingDeclBits.NumPatternEntries = NumPatternEntries; } PatternBindingDecl * @@ -805,9 +805,18 @@ PatternBindingDecl::create(ASTContext &Ctx, SourceLoc StaticLoc, SourceLoc VarLoc, Pattern *Pat, Expr *E, DeclContext *Parent) { - return create(Ctx, StaticLoc, StaticSpelling, VarLoc, - PatternBindingEntry(Pat, E), - Parent); + DeclContext *BindingInitContext = nullptr; + if (!Parent->isLocalContext()) + BindingInitContext = new (Ctx) PatternBindingInitializer(Parent); + + auto Result = create(Ctx, StaticLoc, StaticSpelling, VarLoc, + PatternBindingEntry(Pat, E, BindingInitContext), + Parent); + + if (BindingInitContext) + cast(BindingInitContext)->setBinding(Result, 0); + + return Result; } PatternBindingDecl * @@ -829,7 +838,31 @@ PatternBindingDecl::create(ASTContext &Ctx, SourceLoc StaticLoc, ++elt; auto &newEntry = entries[elt]; newEntry = pe; // This should take care of initializer with flags - PBD->setPattern(elt, pe.getPattern()); + DeclContext *initContext = pe.getInitContext(); + if (!initContext && !Parent->isLocalContext()) { + auto pbi = new (Ctx) PatternBindingInitializer(Parent); + pbi->setBinding(PBD, elt); + initContext = pbi; + } + + PBD->setPattern(elt, pe.getPattern(), initContext); + } + return PBD; +} + +PatternBindingDecl *PatternBindingDecl::createDeserialized( + ASTContext &Ctx, SourceLoc StaticLoc, + StaticSpellingKind StaticSpelling, + SourceLoc VarLoc, + unsigned NumPatternEntries, + DeclContext *Parent) { + size_t Size = totalSizeToAlloc(NumPatternEntries); + void *D = allocateMemoryForDecl(Ctx, Size, + /*ClangNode*/false); + auto PBD = ::new (D) PatternBindingDecl(StaticLoc, StaticSpelling, VarLoc, + NumPatternEntries, Parent); + for (auto &entry : PBD->getMutablePatternList()) { + entry = PatternBindingEntry(nullptr, nullptr, nullptr); } return PBD; } @@ -924,9 +957,11 @@ bool PatternBindingDecl::hasStorage() const { return false; } -void PatternBindingDecl::setPattern(unsigned i, Pattern *P) { +void PatternBindingDecl::setPattern(unsigned i, Pattern *P, + DeclContext *InitContext) { auto PatternList = getMutablePatternList(); PatternList[i].setPattern(P); + PatternList[i].setInitContext(InitContext); // Make sure that any VarDecl's contained within the pattern know about this // PatternBindingDecl as their parent. @@ -3646,7 +3681,7 @@ ParamDecl::ParamDecl(ParamDecl *PD) ArgumentName(PD->getArgumentName()), ArgumentNameLoc(PD->getArgumentNameLoc()), LetVarInOutLoc(PD->getLetVarInOutLoc()), - DefaultValueAndIsVariadic(PD->DefaultValueAndIsVariadic), + DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()), IsTypeLocImplicit(PD->IsTypeLocImplicit), defaultArgumentKind(PD->defaultArgumentKind) { typeLoc = PD->getTypeLoc(); @@ -3788,7 +3823,7 @@ SourceRange ParamDecl::getSourceRange() const { // but we don't have that location info. Extend the back of the range to the // location of the default argument, or the typeloc if they are valid. if (auto expr = getDefaultValue()) { - auto endLoc = expr->getExpr()->getEndLoc(); + auto endLoc = expr->getEndLoc(); if (endLoc.isValid()) return SourceRange(range.Start, endLoc); } @@ -3816,6 +3851,39 @@ Type ParamDecl::getVarargBaseTy(Type VarArgT) { return T; } +void ParamDecl::setDefaultValue(Expr *E) { + if (!DefaultValueAndIsVariadic.getPointer()) { + if (!E) return; + + DefaultValueAndIsVariadic.setPointer( + getASTContext().Allocate()); + } + + DefaultValueAndIsVariadic.getPointer()->DefaultArg = E; +} + +void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) { + assert(DefaultValueAndIsVariadic.getPointer()); + DefaultValueAndIsVariadic.getPointer()->InitContext = initContext; +} + +void DefaultArgumentInitializer::changeFunction(AbstractFunctionDecl *parent) { + assert(parent->isLocalContext()); + setParent(parent); + + unsigned offset = getIndex(); + for (auto list : parent->getParameterLists()) { + if (offset < list->size()) { + auto param = list->get(offset); + if (param->getDefaultValue()) + param->setDefaultArgumentInitContext(this); + return; + } + + offset -= list->size(); + } +} + /// Determine whether the given Swift type is an integral type, i.e., /// a type that wraps a builtin integer. static bool isIntegralType(Type type) { diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index dcce0521d7740..6a3b5a4c545d2 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -722,7 +722,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const { switch (cast(this)->getInitializerKind()) { case InitializerKind::PatternBinding: { auto init = cast(this); - OS << " PatternBinding 0x" << (void*) init->getBinding(); + OS << " PatternBinding 0x" << (void*) init->getBinding() + << " #" << init->getBindingIndex(); break; } case InitializerKind::DefaultArgument: { @@ -748,7 +749,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, unsigned indent) const { } case LocalDeclContextKind::PatternBindingInitializer: { auto init = cast(local); - OS << " PatternBinding 0x" << (void*) init->getBinding(); + OS << " PatternBinding 0x" << (void*) init->getBinding() + << " #" << init->getBindingIndex(); break; } case LocalDeclContextKind::TopLevelCodeDecl: diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 5079dce142a82..a6a9d73b91786 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -567,22 +567,6 @@ void Expr::forEachChildExpr(const std::function &callback) { this->walk(ChildWalker(callback)); } -Initializer *Expr::findExistingInitializerContext() { - struct FindExistingInitializer : ASTWalker { - Initializer *TheInitializer = nullptr; - std::pair walkToExprPre(Expr *E) override { - assert(!TheInitializer && "continuing to walk after finding context?"); - if (auto closure = dyn_cast(E)) { - TheInitializer = cast(closure->getParent()); - return { false, nullptr }; - } - return { true, E }; - } - } finder; - walk(finder); - return finder.TheInitializer; -} - bool Expr::isTypeReference() const { // If the result isn't a metatype, there's nothing else to do. if (!getType()->is()) diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp index 13e17a13a3efe..9d02c6c136cdc 100644 --- a/lib/AST/Parameter.cpp +++ b/lib/AST/Parameter.cpp @@ -18,7 +18,6 @@ #include "swift/AST/ParameterList.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Expr.h" -#include "swift/AST/ExprHandle.h" using namespace swift; /// TODO: unique and reuse the () parameter list in ASTContext, it is common to @@ -91,6 +90,8 @@ ParameterList *ParameterList::clone(const ASTContext &C, // Remap the ParamDecls inside of the ParameterList. for (auto &decl : params) { + bool hadDefaultArgument =decl->getDefaultValue() != nullptr; + decl = new (C) ParamDecl(decl); if (options & Implicit) decl->setImplicit(); @@ -102,9 +103,8 @@ ParameterList *ParameterList::clone(const ASTContext &C, decl->setName(C.getIdentifier("argument")); // If we're inheriting a default argument, mark it as such. - if (decl->isDefaultArgument() && (options & Inherited)) { + if (hadDefaultArgument && (options & Inherited)) { decl->setDefaultArgumentKind(DefaultArgumentKind::Inherited); - decl->setDefaultValue(nullptr); } } diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index f21220b943722..c953695edcd7d 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -18,7 +18,6 @@ #include "swift/AST/TypeRepr.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ASTVisitor.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/Expr.h" #include "swift/AST/Module.h" #include "swift/AST/Types.h" diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index d6181ef2474b6..982b8bce5b6a0 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3965,12 +3965,6 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, 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. ParserStatus Status; @@ -3992,13 +3986,17 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, // pattern/initializer pairs. auto PBD = PatternBindingDecl::create(Context, StaticLoc, StaticSpelling, VarLoc, PBDEntries, CurDeclContext); - + + // Wire up any initializer contexts we needed. + for (unsigned i : indices(PBDEntries)) { + if (auto initContext = PBDEntries[i].getInitContext()) + cast(initContext)->setBinding(PBD, i); + } + // 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 // up in Decls to be returned to caller. if (topLevelDecl) { - assert(!initContext && - "Shouldn't need an initcontext: TopLevelCode is a local context!"); PBD->setDeclContext(topLevelDecl); auto range = PBD->getSourceRange(); topLevelDecl->setBody(BraceStmt::create(Context, range.Start, @@ -4006,18 +4004,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, Decls.insert(Decls.begin()+NumDeclsInResult, topLevelDecl); 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 // specific spot to get it in before any accessors, which SILGen seems to // want. @@ -4049,12 +4036,17 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, // Remember this pattern/init pair for our ultimate PatternBindingDecl. The // Initializer will be added later when/if it is parsed. - PBDEntries.push_back({pattern, nullptr}); - + PBDEntries.push_back({pattern, nullptr, nullptr}); + Expr *PatternInit = nullptr; // Parse an initializer if present. 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; + // 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 // decl (even though names aren't injected into scope when the initializer @@ -4073,7 +4065,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, // for the PBD we'll eventually create. This allows us to have reasonable // DeclContexts for any closures that may live inside of initializers. if (!CurDeclContext->isLocalContext() && !topLevelDecl && !initContext) - initContext = Context.createPatternBindingContext(CurDeclContext); + initContext = new (Context) PatternBindingInitializer(CurDeclContext); // If we're using a local context (either a TopLevelCodeDecl or a // PatternBindingContext) install it now so that CurDeclContext is set @@ -4110,11 +4102,10 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, PatternInit = init.getPtrOrNull(); PBDEntries.back().setInit(PatternInit); - // If we allocated an initContext and the expression had a closure in it, - // we'll need to keep the initContext around. - if (initContext) - usedInitContext |= initParser->hasClosures(); - + // If we set up an initialization context for a property or module-level + // global, record it. + PBDEntries.back().setInitContext(initContext); + // If we are doing second pass of code completion, we don't want to // suddenly cut off parsing and throw away the declaration. if (init.hasCodeCompletion() && isCodeCompletionFirstPass()) { @@ -4144,6 +4135,11 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, // FIXME: Handle generalized parameters. Expr *paramExpr = nullptr; 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; + // 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 // decl (even though names aren't injected into scope when the parameter @@ -4162,7 +4158,7 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, // This will be recontextualized to a method we synthesize during // type checking. if (!CurDeclContext->isLocalContext() && !topLevelDecl && !initContext) - initContext = Context.createPatternBindingContext(CurDeclContext); + initContext = new (Context) PatternBindingInitializer(CurDeclContext); Optional initParser; Optional topLevelParser; if (topLevelDecl) @@ -4172,7 +4168,8 @@ ParserStatus Parser::parseDeclVar(ParseDeclOptions Flags, initParser.emplace(*this, initContext); auto closure = parseExprClosure(); - usedInitContext = true; + PBDEntries.back().setInitContext(initContext); + if (closure.isParseError()) return makeParserError(); if (closure.hasCodeCompletion()) diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index 51af451cd650b..42c5786af5d32 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -17,7 +17,6 @@ #include "swift/Parse/CodeCompletionCallbacks.h" #include "swift/Parse/Parser.h" #include "swift/AST/ASTWalker.h" -#include "swift/AST/ExprHandle.h" #include "swift/Basic/StringExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" @@ -26,11 +25,11 @@ using namespace swift; /// \brief Determine the kind of a default argument given a parsed /// expression that has not yet been type-checked. -static DefaultArgumentKind getDefaultArgKind(ExprHandle *init) { - if (!init || !init->getExpr()) +static DefaultArgumentKind getDefaultArgKind(Expr *init) { + if (!init) return DefaultArgumentKind::None; - auto magic = dyn_cast(init->getExpr()); + auto magic = dyn_cast(init); if (!magic) return DefaultArgumentKind::Normal; @@ -48,36 +47,31 @@ static DefaultArgumentKind getDefaultArgKind(ExprHandle *init) { } } -void Parser::DefaultArgumentInfo::setFunctionContext(DeclContext *DC) { - assert(DC->isLocalContext()); +void Parser::DefaultArgumentInfo::setFunctionContext(AbstractFunctionDecl *AFD){ for (auto context : ParsedContexts) { - context->changeFunction(DC); + context->changeFunction(AFD); } } static ParserStatus parseDefaultArgument(Parser &P, Parser::DefaultArgumentInfo *defaultArgs, unsigned argIndex, - ExprHandle *&init, + Expr *&init, Parser::ParameterContextKind paramContext) { SourceLoc equalLoc = P.consumeToken(tok::equal); // Enter a fresh default-argument context with a meaningless parent. // We'll change the parent to the function later after we've created // that declaration. - auto initDC = - P.Context.createDefaultArgumentContext(P.CurDeclContext, argIndex); + auto initDC = new (P.Context) DefaultArgumentInitializer(P.CurDeclContext, + argIndex); Parser::ParseFunctionBody initScope(P, initDC); ParserResult initR = P.parseExpr(diag::expected_init_value); - // Give back the default-argument context if we didn't need it. - if (!initScope.hasClosures()) { - P.Context.destroyDefaultArgumentContext(initDC); - - // Otherwise, record it if we're supposed to accept default + // Record the default-argument context if we're supposed to accept default // arguments here. - } else if (defaultArgs) { + if (defaultArgs) { defaultArgs->ParsedContexts.push_back(initDC); } @@ -119,7 +113,7 @@ static ParserStatus parseDefaultArgument(Parser &P, if (initR.isNull()) return makeParserError(); - init = ExprHandle::get(P.Context, initR.get()); + init = initR.get(); return ParserStatus(); } @@ -352,7 +346,7 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc, if (param.EllipsisLoc.isValid() && param.DefaultArg) { // The range of the complete default argument. SourceRange defaultArgRange; - if (auto init = param.DefaultArg->getExpr()) + if (auto init = param.DefaultArg) defaultArgRange = SourceRange(param.EllipsisLoc, init->getEndLoc()); diagnose(EqualLoc, diag::parameter_vararg_default) diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp index b5a5383168824..b8287af21f037 100644 --- a/lib/Parse/ParseType.cpp +++ b/lib/Parse/ParseType.cpp @@ -16,7 +16,6 @@ #include "swift/Parse/Parser.h" #include "swift/AST/Attr.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/TypeLoc.h" #include "swift/Parse/Lexer.h" #include "swift/Parse/CodeCompletionCallbacks.h" diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index e8682ecdca746..8c33561526a72 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -1023,9 +1023,9 @@ void SILGenModule::emitDefaultArgGenerators(SILDeclRef::Loc decl, unsigned index = 0; for (auto paramList : paramLists) { for (auto param : *paramList) { - if (auto handle = param->getDefaultValue()) + if (auto defaultArg = param->getDefaultValue()) emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index), - handle->getExpr()); + defaultArg); ++index; } } diff --git a/lib/Sema/TypeCheckCaptures.cpp b/lib/Sema/TypeCheckCaptures.cpp index ff83e11c63754..b6d2504bedf55 100644 --- a/lib/Sema/TypeCheckCaptures.cpp +++ b/lib/Sema/TypeCheckCaptures.cpp @@ -400,7 +400,7 @@ class FindCapturedVars : public ASTWalker { for (auto *paramList : AFD->getParameterLists()) for (auto param : *paramList) { if (auto E = param->getDefaultValue()) - E->getExpr()->walk(*this); + E->walk(*this); } return false; } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 701ea69b60708..1eb5956cfd1c9 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1921,23 +1921,15 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD, // Enter an initializer context if necessary. PatternBindingInitializer *initContext = nullptr; DeclContext *DC = PBD->getDeclContext(); - bool initContextIsNew = false; if (!DC->isLocalContext()) { - // Check for an existing context created by the parser. initContext = cast_or_null( - init->findExistingInitializerContext()); - - // If we didn't find one, create it. - if (!initContext) { - initContext = Context.createPatternBindingContext(DC); - initContext->setBinding(PBD); - initContextIsNew = true; - } - DC = initContext; + PBD->getPatternList()[patternNumber].getInitContext()); + if (initContext) + DC = initContext; } bool hadError = typeCheckBinding(pattern, init, DC); - PBD->setPattern(patternNumber, pattern); + PBD->setPattern(patternNumber, pattern, initContext); PBD->setInit(patternNumber, init); @@ -1949,14 +1941,8 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD, checkInitializerErrorHandling(initContext, init); } - bool hasClosures = - !hadError && contextualizeInitializer(initContext, init); - - // If we created a fresh context and didn't make any autoclosures, - // destroy the initializer context so it can be recycled. - if (!hasClosures && initContextIsNew) { - Context.destroyPatternBindingContext(initContext); - } + if (!hadError) + (void)contextualizeInitializer(initContext, init); } if (hadError) { diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 6ab832aa27627..3b7492bef1baa 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1018,7 +1018,8 @@ static void validatePatternBindingDecl(TypeChecker &tc, return; } - binding->setPattern(entryNumber, pattern); + binding->setPattern(entryNumber, pattern, + binding->getPatternList()[entryNumber].getInitContext()); // Validate 'static'/'class' on properties in nominal type decls. auto StaticSpelling = binding->getStaticSpelling(); diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 0f87567c9e8d9..0016feb10caca 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -18,7 +18,6 @@ #include "TypeChecker.h" #include "GenericTypeResolver.h" #include "swift/Basic/StringExtras.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/NameLookup.h" diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 3a79328a688ca..327a5d484cd53 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -19,7 +19,6 @@ #include "swift/Subsystems.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/ASTVisitor.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/Identifier.h" #include "swift/AST/NameLookup.h" #include "swift/AST/PrettyStackTrace.h" @@ -1207,46 +1206,25 @@ static void checkDefaultArguments(TypeChecker &tc, ParameterList *params, assert(dc->isLocalContext()); for (auto ¶m : *params) { - unsigned curArgIndex = nextArgIndex++; + ++nextArgIndex; if (!param->getDefaultValue() || !param->hasType() || param->getType()->is()) continue; - auto defaultValueHandle = param->getDefaultValue(); - Expr *e = defaultValueHandle->getExpr(); - - // Re-use an existing initializer context if possible. - auto existingContext = e->findExistingInitializerContext(); - DefaultArgumentInitializer *initContext; - if (existingContext) { - initContext = cast(existingContext); - assert(initContext->getIndex() == curArgIndex); - assert(initContext->getParent() == dc); - - // Otherwise, allocate one temporarily. - } else { - initContext = - tc.Context.createDefaultArgumentContext(dc, curArgIndex); - } + Expr *e = param->getDefaultValue(); + auto initContext = param->getDefaultArgumentInitContext(); // Type-check the initializer, then flag that we did so. - if (tc.typeCheckExpression(e, initContext, - TypeLoc::withoutLoc(param->getType()), - CTP_DefaultParameter)) - defaultValueHandle->setExpr(defaultValueHandle->getExpr(), true); - else - defaultValueHandle->setExpr(e, true); + if (!tc.typeCheckExpression(e, initContext, + TypeLoc::withoutLoc(param->getType()), + CTP_DefaultParameter)) + param->setDefaultValue(e); tc.checkInitializerErrorHandling(initContext, e); // Walk the checked initializer and contextualize any closures // we saw there. - bool hasClosures = tc.contextualizeInitializer(initContext, e); - - // If we created a new context and didn't run into any autoclosures - // during the walk, give the context back to the ASTContext. - if (!hasClosures && !existingContext) - tc.Context.destroyDefaultArgumentContext(initContext); + (void)tc.contextualizeInitializer(initContext, e); } } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index fddb685f28cd5..af2d629882d86 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -22,7 +22,6 @@ #include "swift/Strings.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/ASTWalker.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/NameLookup.h" #include "swift/AST/PrettyStackTrace.h" diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index c938524530a75..96b29c87e6ac4 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -20,7 +20,6 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/Attr.h" -#include "swift/AST/ExprHandle.h" #include "swift/AST/Identifier.h" #include "swift/AST/ModuleLoader.h" #include "swift/AST/NameLookup.h" diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index ff1ec85d28ef1..caec46ae9bb59 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -1507,13 +1507,16 @@ DeclContext *ModuleFile::getLocalDeclContext(DeclContextID DCID) { case decls_block::PATTERN_BINDING_INITIALIZER_CONTEXT: { DeclID bindingID; + uint32_t bindingIndex; decls_block::PatternBindingInitializerLayout::readRecord(scratch, - bindingID); + bindingID, + bindingIndex); auto decl = getDecl(bindingID); PatternBindingDecl *binding = cast(decl); - declContextOrOffset = new (ctx) - SerializedPatternBindingInitializer(binding); + if (!declContextOrOffset.isComplete()) + declContextOrOffset = new (ctx) + SerializedPatternBindingInitializer(binding, bindingIndex); break; } @@ -2693,29 +2696,25 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { bool isStatic; uint8_t RawStaticSpelling; unsigned numPatterns; + ArrayRef initContextIDs; decls_block::PatternBindingLayout::readRecord(scratch, contextID, isImplicit, isStatic, RawStaticSpelling, - numPatterns); - SmallVector patterns; - patterns.reserve(numPatterns); - for (unsigned i = 0; i != numPatterns; ++i) { - patterns.push_back({ maybeReadPattern(), nullptr }); - assert(patterns.back().getPattern()); - } - + numPatterns, + initContextIDs); auto StaticSpelling = getActualStaticSpellingKind(RawStaticSpelling); if (!StaticSpelling.hasValue()) { error(); return nullptr; } - auto binding = PatternBindingDecl::create(ctx, SourceLoc(), - StaticSpelling.getValue(), - SourceLoc(), patterns, - getDeclContext(contextID)); + auto binding = + PatternBindingDecl::createDeserialized(ctx, SourceLoc(), + StaticSpelling.getValue(), + SourceLoc(), numPatterns, + getDeclContext(contextID)); binding->setEarlyAttrValidation(true); declOrOffset = binding; @@ -2724,6 +2723,15 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (isImplicit) binding->setImplicit(); + for (unsigned i = 0; i != numPatterns; ++i) { + auto pattern = maybeReadPattern(); + assert(pattern); + DeclContext *initContext = nullptr; + if (!initContextIDs.empty()) + initContext = getDeclContext(initContextIDs[i]); + binding->setPattern(i, pattern, initContext); + } + break; } diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 842116a58fd64..2dc445f02dd69 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1845,11 +1845,13 @@ void Serializer::writeDeclContext(const DeclContext *DC) { declOrDeclContextID, isDecl); } -void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding) { +void Serializer::writePatternBindingInitializer(PatternBindingDecl *binding, + unsigned bindingIndex) { using namespace decls_block; auto abbrCode = DeclTypeAbbrCodes[PatternBindingInitializerLayout::Code]; PatternBindingInitializerLayout::emitRecord(Out, ScratchRecord, - abbrCode, addDeclRef(binding)); + abbrCode, addDeclRef(binding), + bindingIndex); } void @@ -1896,7 +1898,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) { case DeclContextKind::Initializer: { if (auto PBI = dyn_cast(DC)) { - writePatternBindingInitializer(PBI->getBinding()); + writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex()); } else if (auto DAI = dyn_cast(DC)) { writeDefaultArgumentInitializer(DAI->getParent(), DAI->getIndex()); } @@ -1928,7 +1930,7 @@ void Serializer::writeLocalDeclContext(const DeclContext *DC) { } case LocalDeclContextKind::PatternBindingInitializer: { auto PBI = cast(local); - writePatternBindingInitializer(PBI->getBinding()); + writePatternBindingInitializer(PBI->getBinding(), PBI->getBindingIndex()); return; } case LocalDeclContextKind::TopLevelCodeDecl: { @@ -2104,13 +2106,25 @@ void Serializer::writeDecl(const Decl *D) { verifyAttrSerializable(binding); auto contextID = addDeclContextRef(binding->getDeclContext()); + SmallVector initContextIDs; + for (unsigned i : range(binding->getNumPatternEntries())) { + auto initContextID = + addDeclContextRef(binding->getPatternList()[i].getInitContext()); + if (!initContextIDs.empty()) { + initContextIDs.push_back(initContextID); + } else if (initContextID) { + initContextIDs.append(i, 0); + initContextIDs.push_back(initContextID); + } + } unsigned abbrCode = DeclTypeAbbrCodes[PatternBindingLayout::Code]; PatternBindingLayout::emitRecord( Out, ScratchRecord, abbrCode, contextID, binding->isImplicit(), binding->isStatic(), uint8_t(getStableStaticSpelling(binding->getStaticSpelling())), - binding->getNumPatternEntries()); + binding->getNumPatternEntries(), + initContextIDs); for (auto entry : binding->getPatternList()) { writePattern(entry.getPattern()); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 7f4ae2cbb78dd..dc8486b5d722c 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -293,7 +293,8 @@ class Serializer { void writeLocalDeclContext(const DeclContext *DC); /// 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. void writeDefaultArgumentInitializer(const DeclContext *parentContext, unsigned index);