diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index d4168a1a25485..8efb23b3c47e6 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1374,6 +1374,82 @@ class alignas(RequirementRepr) TrailingWhereClause final : } }; +class GenericContext : public DeclContext { +private: + GenericParamList *GenericParams = nullptr; + + /// The trailing where clause. + /// + /// Note that this is not currently serialized, because semantic analysis + /// moves the trailing where clause into the generic parameter list. + TrailingWhereClause *TrailingWhere = nullptr; + + /// The generic signature or environment of this declaration. + /// + /// When this declaration stores only a signature, the generic + /// environment will be lazily loaded. + mutable llvm::PointerUnion + GenericSigOrEnv; + + /// Lazily populate the generic environment. + GenericEnvironment *getLazyGenericEnvironmentSlow() const; + +protected: + GenericContext(DeclContextKind Kind, DeclContext *Parent) + : DeclContext(Kind, Parent) { } + +public: + /// \brief Retrieve the set of parameters to a generic subscript, or null if + /// this subscript is not generic. + GenericParamList *getGenericParams() const { return GenericParams; } + + void setGenericParams(GenericParamList *GenericParams); + + /// \brief Determine whether this subscript has generic parameters + /// of its own. + bool isGeneric() const { return GenericParams != nullptr; } + + /// Retrieve the trailing where clause for this extension, if any. + TrailingWhereClause *getTrailingWhereClause() const { + return TrailingWhere; + } + + /// Set the trailing where clause for this extension. + void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) { + TrailingWhere = trailingWhereClause; + } + + /// Retrieve the generic signature for this subscript. + GenericSignature *getGenericSignature() const; + + /// Retrieve the generic context for this subscript. + GenericEnvironment *getGenericEnvironment() const; + + /// Retrieve the innermost generic parameter types. + ArrayRef getInnermostGenericParamTypes() const { + if (auto sig = getGenericSignature()) + return sig->getInnermostGenericParams(); + else + return { }; + } + + /// Retrieve the generic requirements. + ArrayRef getGenericRequirements() const { + if (auto sig = getGenericSignature()) + return sig->getRequirements(); + else + return { }; + } + + /// Set a lazy generic environment. + void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, + GenericSignature *genericSig, + uint64_t genericEnvData); + + /// Set the generic context of this subscript. + void setGenericEnvironment(GenericEnvironment *genericEnv); +}; + /// Describes what kind of name is being imported. /// /// If the enumerators here are changed, make sure to update all diagnostics @@ -1483,7 +1559,7 @@ class ImportDecl final : public Decl, /// ExtensionDecl - This represents a type extension containing methods /// associated with the type. This is not a ValueDecl and has no Type because /// there are no runtime values of the Extension's type. -class ExtensionDecl final : public Decl, public DeclContext, +class ExtensionDecl final : public Decl, public GenericContext, public IterableDeclContext { SourceLoc ExtensionLoc; // Location of 'extension' keyword. SourceRange Braces; @@ -1491,24 +1567,8 @@ class ExtensionDecl final : public Decl, public DeclContext, /// The type being extended. TypeLoc ExtendedType; - /// The generic parameters of the extension. - GenericParamList *GenericParams = nullptr; - - /// The generic signature or environment of this extension. - /// - /// When this extension stores only a signature, the generic environment - /// will be lazily loaded. - mutable llvm::PointerUnion - GenericSigOrEnv; - MutableArrayRef Inherited; - /// The trailing where clause. - /// - /// Note that this is not currently serialized, because semantic analysis - /// moves the trailing where clause into the generic parameter list. - TrailingWhereClause *TrailingWhere; - /// \brief The next extension in the linked list of extensions. /// /// The bit indicates whether this extension has been resolved to refer to @@ -1543,9 +1603,6 @@ class ExtensionDecl final : public Decl, public DeclContext, /// Slow path for \c takeConformanceLoader(). std::pair takeConformanceLoaderSlow(); - /// Lazily populate the generic environment. - GenericEnvironment *getLazyGenericEnvironmentSlow() const; - public: using Decl::getASTContext; @@ -1566,45 +1623,6 @@ class ExtensionDecl final : public Decl, public DeclContext, SourceRange getBraces() const { return Braces; } void setBraces(SourceRange braces) { Braces = braces; } - /// Retrieve the innermost generic parameter list. - GenericParamList *getGenericParams() const { - return GenericParams; - } - - void setGenericParams(GenericParamList *params); - - /// Retrieve the trailing where clause for this extension, if any. - TrailingWhereClause *getTrailingWhereClause() const { - return TrailingWhere; - } - - /// Set the trailing where clause for this extension. - void setTrailingWhereClause(TrailingWhereClause *trailingWhereClause) { - TrailingWhere = trailingWhereClause; - } - - /// Retrieve the generic requirements. - ArrayRef getGenericRequirements() const { - if (auto sig = getGenericSignature()) - return sig->getRequirements(); - else - return { }; - } - - /// Retrieve the generic signature for this type. - GenericSignature *getGenericSignature() const; - - /// Retrieve the generic context for this type. - GenericEnvironment *getGenericEnvironment() const; - - /// Set a lazy generic environment. - void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData); - - /// Set the generic context of this extension. - void setGenericEnvironment(GenericEnvironment *genericEnv); - /// Retrieve the type being extended. Type getExtendedType() const { return ExtendedType.getType(); } @@ -2351,61 +2369,13 @@ class TypeDecl : public ValueDecl { /// A type declaration that can have generic parameters attached to it. Because /// it has these generic parameters, it is always a DeclContext. -class GenericTypeDecl : public TypeDecl, public DeclContext { - GenericParamList *GenericParams = nullptr; - - /// The generic signature or environment of this type. - /// - /// When this function stores only a signature, the generic environment - /// will be lazily loaded. - mutable llvm::PointerUnion - GenericSigOrEnv; - - /// Lazily populate the generic environment. - GenericEnvironment *getLazyGenericEnvironmentSlow() const; - +class GenericTypeDecl : public TypeDecl, public GenericContext { public: GenericTypeDecl(DeclKind K, DeclContext *DC, Identifier name, SourceLoc nameLoc, MutableArrayRef inherited, GenericParamList *GenericParams); - GenericParamList *getGenericParams() const { return GenericParams; } - - /// Provide the set of parameters to a generic type, or null if - /// this function is not generic. - void setGenericParams(GenericParamList *params); - - /// Retrieve the innermost generic parameter types. - ArrayRef getInnermostGenericParamTypes() const { - if (auto sig = getGenericSignature()) - return sig->getInnermostGenericParams(); - else - return { }; - } - - /// Retrieve the generic requirements. - ArrayRef getGenericRequirements() const { - if (auto sig = getGenericSignature()) - return sig->getRequirements(); - else - return { }; - } - - /// Retrieve the generic signature for this type. - GenericSignature *getGenericSignature() const; - - /// Retrieve the generic context for this type. - GenericEnvironment *getGenericEnvironment() const; - - /// Set a lazy generic environment. - void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData); - - /// Set the generic context of this function. - void setGenericEnvironment(GenericEnvironment *genericEnv); - // Resolve ambiguity due to multiple base classes. using TypeDecl::getASTContext; using DeclContext::operator new; @@ -4639,7 +4609,7 @@ struct ImportAsMemberStatus { }; /// \brief Base class for function-like declarations. -class AbstractFunctionDecl : public ValueDecl, public DeclContext { +class AbstractFunctionDecl : public ValueDecl, public GenericContext { public: enum class BodyKind { /// The function did not have a body in the source code file. @@ -4690,15 +4660,6 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { SourceRange BodyRange; }; - GenericParamList *GenericParams; - - /// The generic signature or environment of this function. - /// - /// When this function stores only a signature, the generic environment - /// will be lazily loaded. - mutable llvm::PointerUnion - GenericSigOrEnv; - CaptureInfo Captures; /// Location of the 'throws' token. @@ -4711,8 +4672,8 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { unsigned NumParameterLists, GenericParamList *GenericParams) : ValueDecl(Kind, Parent, Name, NameLoc), - DeclContext(DeclContextKind::AbstractFunctionDecl, Parent), - Body(nullptr), GenericParams(nullptr), ThrowsLoc(ThrowsLoc) { + GenericContext(DeclContextKind::AbstractFunctionDecl, Parent), + Body(nullptr), ThrowsLoc(ThrowsLoc) { setBodyKind(BodyKind::None); setGenericParams(GenericParams); AbstractFunctionDeclBits.NumParameterLists = NumParameterLists; @@ -4727,30 +4688,11 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { AbstractFunctionDeclBits.BodyKind = unsigned(K); } - void setGenericParams(GenericParamList *GenericParams); - - /// Lazily populate the generic environment. - GenericEnvironment *getLazyGenericEnvironmentSlow() const; - public: /// \brief Should this declaration be treated as if annotated with transparent /// attribute. bool isTransparent() const; - /// Retrieve the generic signature for this function. - GenericSignature *getGenericSignature() const; - - /// Retrieve the generic context for this function. - GenericEnvironment *getGenericEnvironment() const; - - /// Set a lazy generic environment. - void setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData); - - /// Set the generic context of this function. - void setGenericEnvironment(GenericEnvironment *genericEnv); - // Expose our import as member status bool isImportAsMember() const { return IAMStatus.isImportAsMember(); } bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); } @@ -4930,14 +4872,6 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { } ParamDecl *getImplicitSelfDecl(); - /// \brief Retrieve the set of parameters to a generic function, or null if - /// this function is not generic. - GenericParamList *getGenericParams() const { return GenericParams; } - - /// \brief Determine whether this is a generic function, which can only be - /// used when each of the archetypes is bound to a particular concrete type. - bool isGeneric() const { return GenericParams != nullptr; } - /// Retrieve the declaration that this method overrides, if any. AbstractFunctionDecl *getOverriddenDecl() const; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 291a1007cfa34..86eeff0222c34 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -546,6 +546,106 @@ TrailingWhereClause *TrailingWhereClause::create( return new (mem) TrailingWhereClause(whereLoc, requirements); } +void GenericContext::setGenericParams(GenericParamList *params) { + GenericParams = params; + + if (GenericParams) { + for (auto param : *GenericParams) + param->setDeclContext(this); + } +} + +GenericSignature *GenericContext::getGenericSignature() const { + if (auto genericEnv = GenericSigOrEnv.dyn_cast()) + return genericEnv->getGenericSignature(); + + if (auto genericSig = GenericSigOrEnv.dyn_cast()) + return genericSig; + + return nullptr; +} + +GenericEnvironment *GenericContext::getGenericEnvironment() const { + // Fast case: we already have a generic environment. + if (auto genericEnv = GenericSigOrEnv.dyn_cast()) + return genericEnv; + + // If we only have a generic signature, build the generic environment. + if (GenericSigOrEnv.dyn_cast()) + return getLazyGenericEnvironmentSlow(); + + return nullptr; +} + +void GenericContext::setGenericEnvironment(GenericEnvironment *genericEnv) { + assert((GenericSigOrEnv.isNull() || + getGenericSignature()->getCanonicalSignature() == + genericEnv->getGenericSignature()->getCanonicalSignature()) && + "set a generic environment with a different generic signature"); + this->GenericSigOrEnv = genericEnv; + if (genericEnv) + genericEnv->setOwningDeclContext(this); +} + +GenericEnvironment * +GenericContext::getLazyGenericEnvironmentSlow() const { + assert(GenericSigOrEnv.is() && + "not a lazily deserialized generic environment"); + + GenericEnvironment *genericEnv; + + if (auto *extensionDecl = dyn_cast(this)) { + auto contextData = getASTContext().getOrCreateLazyIterableContextData( + extensionDecl, nullptr); + genericEnv = contextData->loader->loadGenericEnvironment( + extensionDecl, contextData->genericEnvData); + } else if (auto *typeDecl = dyn_cast(this)) { + auto contextData = getASTContext().getOrCreateLazyGenericTypeData( + typeDecl, nullptr); + genericEnv = contextData->loader->loadGenericEnvironment( + typeDecl, contextData->genericEnvData); + } else if (auto *funcDecl = dyn_cast(this)) { + auto contextData = getASTContext().getOrCreateLazyFunctionContextData( + funcDecl, nullptr); + genericEnv = contextData->loader->loadGenericEnvironment( + funcDecl, contextData->genericEnvData); + } else { + llvm_unreachable("Bad GenericContext kind"); + } + + const_cast(this)->setGenericEnvironment(genericEnv); + ++NumLazyGenericEnvironmentsLoaded; + return genericEnv; +} + +void GenericContext::setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, + GenericSignature *genericSig, + uint64_t genericEnvData) { + assert(GenericSigOrEnv.isNull() && "already have a generic signature"); + GenericSigOrEnv = genericSig; + + if (auto *extensionDecl = dyn_cast(this)) { + auto contextData = + getASTContext().getOrCreateLazyIterableContextData( + extensionDecl, lazyLoader); + contextData->genericEnvData = genericEnvData; + } else if (auto *typeDecl = dyn_cast(this)) { + auto contextData = + getASTContext().getOrCreateLazyGenericTypeData( + typeDecl, lazyLoader); + contextData->genericEnvData = genericEnvData; + } else if (auto *funcDecl = dyn_cast(this)) { + auto contextData = + getASTContext().getOrCreateLazyFunctionContextData( + funcDecl, lazyLoader); + contextData->genericEnvData = genericEnvData; + } else { + llvm_unreachable("Bad GenericContext kind"); + } + + ++NumLazyGenericEnvironments; +} + ImportDecl *ImportDecl::create(ASTContext &Ctx, DeclContext *DC, SourceLoc ImportLoc, ImportKind Kind, SourceLoc KindLoc, @@ -673,17 +773,17 @@ ExtensionDecl::ExtensionDecl(SourceLoc extensionLoc, DeclContext *parent, TrailingWhereClause *trailingWhereClause) : Decl(DeclKind::Extension, parent), - DeclContext(DeclContextKind::ExtensionDecl, parent), + GenericContext(DeclContextKind::ExtensionDecl, parent), IterableDeclContext(IterableDeclContextKind::ExtensionDecl), ExtensionLoc(extensionLoc), ExtendedType(extendedType), - Inherited(inherited), - TrailingWhere(trailingWhereClause) + Inherited(inherited) { ExtensionDeclBits.Validated = false; ExtensionDeclBits.CheckedInheritanceClause = false; ExtensionDeclBits.DefaultAndMaxAccessLevel = 0; ExtensionDeclBits.HasLazyConformances = false; + setTrailingWhereClause(trailingWhereClause); } ExtensionDecl *ExtensionDecl::create(ASTContext &ctx, SourceLoc extensionLoc, @@ -707,72 +807,6 @@ ExtensionDecl *ExtensionDecl::create(ASTContext &ctx, SourceLoc extensionLoc, return result; } -void ExtensionDecl::setGenericParams(GenericParamList *params) { - GenericParams = params; - - if (GenericParams) { - for (auto param : *GenericParams) - param->setDeclContext(this); - } -} - -GenericSignature *ExtensionDecl::getGenericSignature() const { - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv->getGenericSignature(); - - if (auto genericSig = GenericSigOrEnv.dyn_cast()) - return genericSig; - - return nullptr; -} - -GenericEnvironment *ExtensionDecl::getGenericEnvironment() const { - // Fast case: we already have a generic environment. - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv; - - // If we only have a generic signature, build the generic environment. - if (GenericSigOrEnv.dyn_cast()) - return getLazyGenericEnvironmentSlow(); - - return nullptr; -} - -void ExtensionDecl::setGenericEnvironment(GenericEnvironment *genericEnv) { - assert((GenericSigOrEnv.isNull() || - getGenericSignature()->getCanonicalSignature() == - genericEnv->getGenericSignature()->getCanonicalSignature()) && - "set a generic environment with a different generic signature"); - this->GenericSigOrEnv = genericEnv; - if (genericEnv) - genericEnv->setOwningDeclContext(this); -} - -GenericEnvironment * -ExtensionDecl::getLazyGenericEnvironmentSlow() const { - assert(GenericSigOrEnv.is() && - "not a lazily deserialized generic environment"); - auto contextData = getASTContext().getOrCreateLazyIterableContextData(this, - nullptr); - auto genericEnv = contextData->loader->loadGenericEnvironment( - this, contextData->genericEnvData); - const_cast(this)->setGenericEnvironment(genericEnv); - ++NumLazyGenericEnvironmentsLoaded; - return genericEnv; -} - -void ExtensionDecl::setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData) { - assert(GenericSigOrEnv.isNull() && "already have a generic signature"); - GenericSigOrEnv = genericSig; - - auto contextData = - getASTContext().getOrCreateLazyIterableContextData(this, lazyLoader); - contextData->genericEnvData = genericEnvData; - ++NumLazyGenericEnvironments; -} - DeclRange ExtensionDecl::getMembers() const { loadAllMembers(); return IterableDeclContext::getMembers(); @@ -2178,79 +2212,10 @@ GenericTypeDecl::GenericTypeDecl(DeclKind K, DeclContext *DC, MutableArrayRef inherited, GenericParamList *GenericParams) : TypeDecl(K, DC, name, nameLoc, inherited), - DeclContext(DeclContextKind::GenericTypeDecl, DC) { + GenericContext(DeclContextKind::GenericTypeDecl, DC) { setGenericParams(GenericParams); } - -void GenericTypeDecl::setGenericParams(GenericParamList *params) { - // Set the specified generic parameters onto this type declaration, setting - // the parameters' context along the way. - GenericParams = params; - if (params) - for (auto Param : *params) - Param->setDeclContext(this); -} - -GenericSignature *GenericTypeDecl::getGenericSignature() const { - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv->getGenericSignature(); - - if (auto genericSig = GenericSigOrEnv.dyn_cast()) - return genericSig; - - return nullptr; -} - -GenericEnvironment *GenericTypeDecl::getGenericEnvironment() const { - // Fast case: we already have a generic environment. - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv; - - // If we only have a generic signature, build the generic environment. - if (GenericSigOrEnv.dyn_cast()) - return getLazyGenericEnvironmentSlow(); - - return nullptr; -} - -/// Set the generic context of this function. -void GenericTypeDecl::setGenericEnvironment(GenericEnvironment *genericEnv) { - assert((GenericSigOrEnv.isNull() || - getGenericSignature()->getCanonicalSignature() == - genericEnv->getGenericSignature()->getCanonicalSignature()) && - "set a generic environment with a different generic signature"); - this->GenericSigOrEnv = genericEnv; - - if (genericEnv) - genericEnv->setOwningDeclContext(this); -} - -GenericEnvironment * -GenericTypeDecl::getLazyGenericEnvironmentSlow() const { - assert(GenericSigOrEnv.is() && - "not a lazily deserialized generic environment"); - auto contextData = getASTContext().getOrCreateLazyGenericTypeData(this, - nullptr); - auto genericEnv = contextData->loader->loadGenericEnvironment( - this, contextData->genericEnvData); - const_cast(this)->setGenericEnvironment(genericEnv); - ++NumLazyGenericEnvironmentsLoaded; - return genericEnv; -} - -void GenericTypeDecl::setLazyGenericEnvironment(LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData) { - assert(GenericSigOrEnv.isNull() && "already have a generic signature"); - GenericSigOrEnv = genericSig; - - auto contextData = - getASTContext().getOrCreateLazyGenericTypeData(this, lazyLoader); - contextData->genericEnvData = genericEnvData; - ++NumLazyGenericEnvironments; -} - TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, SourceLoc EqualLoc, Identifier Name, SourceLoc NameLoc, GenericParamList *GenericParams, DeclContext *DC) @@ -4059,66 +4024,6 @@ SourceRange SubscriptDecl::getSourceRange() const { return { getSubscriptLoc(), ElementTy.getSourceRange().End }; } -GenericSignature *AbstractFunctionDecl::getGenericSignature() const { - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv->getGenericSignature(); - - if (auto genericSig = GenericSigOrEnv.dyn_cast()) - return genericSig; - - return nullptr; -} - -GenericEnvironment *AbstractFunctionDecl::getGenericEnvironment() const { - // Fast case: we already have a generic environment. - if (auto genericEnv = GenericSigOrEnv.dyn_cast()) - return genericEnv; - - // If we only have a generic signature, build the generic environment. - if (GenericSigOrEnv.dyn_cast()) - return getLazyGenericEnvironmentSlow(); - - return nullptr; -} - -void -AbstractFunctionDecl::setGenericEnvironment(GenericEnvironment *genericEnv) { - assert((GenericSigOrEnv.isNull() || - getGenericSignature()->getCanonicalSignature() == - genericEnv->getGenericSignature()->getCanonicalSignature()) && - "set a generic environment with a different generic signature"); - this->GenericSigOrEnv = genericEnv; - - if (genericEnv) - genericEnv->setOwningDeclContext(this); -} - -GenericEnvironment * -AbstractFunctionDecl::getLazyGenericEnvironmentSlow() const { - assert(GenericSigOrEnv.is() && - "not a lazily deserialized generic environment"); - auto contextData = - getASTContext().getOrCreateLazyFunctionContextData(this, nullptr); - auto genericEnv = contextData->loader->loadGenericEnvironment( - this, contextData->genericEnvData); - const_cast(this)->setGenericEnvironment(genericEnv); - ++NumLazyGenericEnvironmentsLoaded; - return genericEnv; -} - -void AbstractFunctionDecl::setLazyGenericEnvironment( - LazyMemberLoader *lazyLoader, - GenericSignature *genericSig, - uint64_t genericEnvData) { - assert(GenericSigOrEnv.isNull() && "already have a generic signature"); - GenericSigOrEnv = genericSig; - - auto contextData = - getASTContext().getOrCreateLazyFunctionContextData(this, lazyLoader); - contextData->genericEnvData = genericEnvData; - ++NumLazyGenericEnvironments; -} - Type AbstractFunctionDecl::computeInterfaceSelfType(bool isInitializingCtor, bool wantDynamicSelf) { auto *dc = getDeclContext(); @@ -4218,16 +4123,6 @@ DeclName AbstractFunctionDecl::getEffectiveFullName() const { return DeclName(); } -void AbstractFunctionDecl::setGenericParams(GenericParamList *GP) { - // Set the specified generic parameters onto this abstract function, setting - // the parameters' context to the function along the way. - GenericParams = GP; - if (GP) - for (auto Param : *GP) - Param->setDeclContext(this); -} - - /// \brief This method returns the implicit 'self' decl. /// /// Note that some functions don't have an implicit 'self' decl, for example,