diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 78e8c15882018..9c7a5b058bfb2 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -250,11 +250,19 @@ class ArchetypeBuilder { /// \brief Get a generic signature based on the provided complete list /// of generic parameter types. /// - /// \returns a generic signature build based on the provided list of + /// \returns a generic signature built from the provided list of /// generic parameter types. GenericSignature * getGenericSignature(ArrayRef genericParamsTypes); + /// \brief Get a generic context based on the complete list of generic + /// parameter types. + /// + /// \returns a generic context built from the provided list of + /// generic parameter types. + GenericEnvironment *getGenericEnvironment( + ArrayRef genericParamsTypes); + /// Infer requirements from the given type, recursively. /// /// This routine infers requirements from a type that occurs within the @@ -315,27 +323,20 @@ class ArchetypeBuilder { /// parameter. ArchetypeType *getArchetype(GenericTypeParamDecl *GenericParam); - /// \brief Retrieve the array of all of the archetypes produced during - /// archetype assignment. The 'primary' archetypes will occur first in this - /// list. - ArrayRef getAllArchetypes(); - /// Map an interface type to a contextual type. - static Type mapTypeIntoContext(const DeclContext *dc, Type type, - LazyResolver *resolver = nullptr); + static Type mapTypeIntoContext(const DeclContext *dc, Type type); /// Map an interface type to a contextual type. static Type mapTypeIntoContext(ModuleDecl *M, - GenericParamList *genericParams, - Type type, - LazyResolver *resolver = nullptr); + GenericEnvironment *genericEnv, + Type type); /// Map a contextual type to an interface type. static Type mapTypeOutOfContext(const DeclContext *dc, Type type); /// Map a contextual type to an interface type. static Type mapTypeOutOfContext(ModuleDecl *M, - GenericParamList *genericParams, + GenericEnvironment *genericEnv, Type type); using SameTypeRequirement diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 964a2dc927eea..e1512f05f8922 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -35,6 +35,7 @@ namespace swift { enum class AccessSemantics : unsigned char; class ApplyExpr; class ArchetypeBuilder; + class GenericEnvironment; class ArchetypeType; class ASTContext; class ASTPrinter; @@ -1059,7 +1060,6 @@ class GenericParamList final : unsigned NumParams; SourceLoc WhereLoc; MutableArrayRef Requirements; - ArrayRef AllArchetypes; GenericParamList *OuterParameters; @@ -1109,28 +1109,6 @@ class GenericParamList final : MutableArrayRef Requirements, SourceLoc RAngleLoc); - /// Create a new generic parameter list with the same parameters and - /// requirements as this one, but parented to a different outer parameter - /// list. - GenericParamList *cloneWithOuterParameters(const ASTContext &Context, - GenericParamList *Outer) { - auto clone = create(Context, - SourceLoc(), - getParams(), - SourceLoc(), - getRequirements(), - SourceLoc()); - clone->setAllArchetypes(getAllArchetypes()); - clone->setOuterParameters(Outer); - return clone; - } - - /// Create an empty generic parameter list. - static GenericParamList *getEmpty(ASTContext &Context) { - // TODO: Could probably unique this in the AST context. - return create(Context, SourceLoc(), {}, SourceLoc(), {}, SourceLoc()); - } - MutableArrayRef getParams() { return {getTrailingObjects(), NumParams}; } @@ -1148,12 +1126,6 @@ class GenericParamList final : const_iterator begin() const { return getParams().begin(); } const_iterator end() const { return getParams().end(); } - /// Get the total number of parameters, including those from parent generic - /// parameter lists. - unsigned totalSize() const { - return NumParams + (OuterParameters ? OuterParameters->totalSize() : 0); - } - /// \brief Retrieve the location of the 'where' keyword, or an invalid /// location if 'where' was not present. SourceLoc getWhereLoc() const { return WhereLoc; } @@ -1199,24 +1171,7 @@ class GenericParamList final : /// main part of a declaration's signature. void addTrailingWhereClause(ASTContext &ctx, SourceLoc trailingWhereLoc, ArrayRef trailingRequirements); - - /// \brief Retrieves the list containing all archetypes described by this - /// generic parameter clause. - /// - /// In this list of archetypes, the primary archetypes come first followed by - /// any non-primary archetypes (i.e., those archetypes that encode associated - /// types of another archetype). - /// - /// This does not include archetypes from the outer generic parameter list(s). - ArrayRef getAllArchetypes() const { return AllArchetypes; } - /// \brief Sets all archetypes *without* copying the source array. - void setAllArchetypes(ArrayRef AA) { - assert(AA.size() >= size() - && "allArchetypes is smaller than number of generic params?!"); - AllArchetypes = AA; - } - /// \brief Retrieve the outer generic parameter list, which provides the /// generic parameters of the context in which this generic parameter list /// exists. @@ -1270,36 +1225,6 @@ class GenericParamList final : return depth; } - /// Derive a contextual type substitution map from a substitution array. - /// This is just like GenericSignature::getSubstitutionMap(), except - /// with contextual types instead of interface types. - void - getSubstitutionMap(ModuleDecl *mod, - GenericSignature *sig, - ArrayRef subs, - TypeSubstitutionMap &subsMap, - ArchetypeConformanceMap &conformanceMap) const; - - /// Derive the all-archetypes list for the given list of generic - /// parameters. - static ArrayRef - deriveAllArchetypes(ArrayRef params, - SmallVectorImpl &archetypes); - - void getForwardingSubstitutionMap(TypeSubstitutionMap &result) const; - - ArrayRef - getForwardingSubstitutions(GenericSignature *sig) const; - - /// Collect the nested archetypes of an archetype into the given - /// collection. - /// - /// \param known - the set of archetypes already present in `all` - /// \param all - the output list of archetypes - static void addNestedArchetypes(ArchetypeType *archetype, - SmallPtrSetImpl &known, - SmallVectorImpl &all); - void print(raw_ostream &OS); void dump(); }; @@ -1472,6 +1397,12 @@ class ExtensionDecl final : public Decl, public DeclContext, /// the parsed representation, and not part of the module file. GenericSignature *GenericSig = nullptr; + /// \brief The generic context of this extension. + /// + /// This is the mapping between interface types and archetypes for the + /// generic parameters of this extension. + GenericEnvironment *GenericEnv = nullptr; + MutableArrayRef Inherited; /// The trailing where clause. @@ -1555,7 +1486,19 @@ class ExtensionDecl final : public Decl, public DeclContext, GenericSignature *getGenericSignature() const { return GenericSig; } /// Set the generic signature of this extension. - void setGenericSignature(GenericSignature *sig); + void setGenericSignature(GenericSignature *sig) { + assert(!GenericSig && "Already have generic signature"); + GenericSig = sig; + } + + /// Retrieve the generic context for this extension. + GenericEnvironment *getGenericEnvironment() const { return GenericEnv; } + + /// Set the generic context of this extension. + void setGenericEnvironment(GenericEnvironment *env) { + assert(!GenericEnv && "Already have generic context"); + GenericEnv = env; + } /// Retrieve the generic requirements. ArrayRef getGenericRequirements() const; @@ -2306,6 +2249,12 @@ class GenericTypeDecl : public TypeDecl, public DeclContext { /// the parsed representation, and not part of the module file. GenericSignature *GenericSig = nullptr; + /// \brief The generic context of this type. + /// + /// This is the mapping between interface types and archetypes for the + /// generic parameters of this type. + GenericEnvironment *GenericEnv = nullptr; + /// \brief Whether or not the generic signature of the type declaration is /// currently being validated. // TODO: Merge into GenericSig bits. @@ -2324,7 +2273,10 @@ class GenericTypeDecl : public TypeDecl, public DeclContext { void setGenericParams(GenericParamList *params); /// Set the generic signature of this type. - void setGenericSignature(GenericSignature *sig); + void setGenericSignature(GenericSignature *sig) { + assert(!GenericSig && "Already have generic signature"); + GenericSig = sig; + } /// Retrieve the innermost generic parameter types. ArrayRef getInnermostGenericParamTypes() const { @@ -2355,6 +2307,15 @@ class GenericTypeDecl : public TypeDecl, public DeclContext { return ValidatingGenericSignature; } + /// Retrieve the generic context for this type. + GenericEnvironment *getGenericEnvironment() const { return GenericEnv; } + + /// Set the generic context of this type. + void setGenericEnvironment(GenericEnvironment *env) { + assert(!this->GenericEnv && "already have generic context?"); + this->GenericEnv = env; + } + // Resolve ambiguity due to multiple base classes. using TypeDecl::getASTContext; using DeclContext::operator new; @@ -4573,6 +4534,7 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { GenericParamList *GenericParams; GenericSignature *GenericSig; + GenericEnvironment *GenericEnv; CaptureInfo Captures; @@ -4589,7 +4551,7 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { : ValueDecl(Kind, Parent, Name, NameLoc), DeclContext(DeclContextKind::AbstractFunctionDecl, Parent), Body(nullptr), GenericParams(nullptr), GenericSig(nullptr), - ThrowsLoc(ThrowsLoc) { + GenericEnv(nullptr), ThrowsLoc(ThrowsLoc) { setBodyKind(BodyKind::None); setGenericParams(GenericParams); AbstractFunctionDeclBits.NumParameterLists = NumParameterLists; @@ -4616,6 +4578,15 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { return GenericSig; } + /// Retrieve the generic context for this function. + GenericEnvironment *getGenericEnvironment() const { return GenericEnv; } + + /// Set the generic context of this function. + void setGenericEnvironment(GenericEnvironment *GenericEnv) { + assert(!this->GenericEnv && "already have generic context?"); + this->GenericEnv = GenericEnv; + } + // Expose our import as member status bool isImportAsMember() const { return IAMStatus.isImportAsMember(); } bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); } diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h index 041d4fe58d050..0e8fee97fcab7 100644 --- a/include/swift/AST/DeclContext.h +++ b/include/swift/AST/DeclContext.h @@ -35,6 +35,7 @@ namespace llvm { namespace swift { class AbstractFunctionDecl; + class GenericEnvironment; class ASTContext; class ASTWalker; class CanType; @@ -284,14 +285,19 @@ class alignas(1 << DeclContextAlignInBits) DeclContext { /// type for non-type contexts. Type getDeclaredInterfaceType() const; - /// \brief Retrieve the innermost generic parameters introduced by this - /// context or one of its parent contexts, or null if this context is not - /// directly dependent on any generic parameters. + /// \brief Retrieve the innermost generic parameters of this context or any + /// of its parents. + /// + /// FIXME: Remove this GenericParamList *getGenericParamsOfContext() const; - /// \brief Retrieve the interface generic type parameters and requirements - /// exposed by this context. + /// \brief Retrieve the innermost generic signature of this context or any + /// of its parents. GenericSignature *getGenericSignatureOfContext() const; + + /// \brief Retrieve the innermost archetypes of this context or any + /// of its parents. + GenericEnvironment *getGenericEnvironmentOfContext() const; /// Returns this or the first local parent context, or nullptr if it is not /// contained in one. diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h new file mode 100644 index 0000000000000..14592b4a4b6b1 --- /dev/null +++ b/include/swift/AST/GenericEnvironment.h @@ -0,0 +1,77 @@ +//===--- GenericEnvironment.h - Generic Environment AST ---------*- 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 GenericEnvironment class. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_AST_GENERIC_ENVIRONMENT_H +#define SWIFT_AST_GENERIC_ENVIRONMENT_H + +#include "swift/AST/ProtocolConformance.h" + +namespace swift { + +class ASTContext; + +/// Describes the mapping between archetypes and interface types for the +/// generic parameters of a DeclContext. +class GenericEnvironment final { + TypeSubstitutionMap ArchetypeToInterfaceMap; + TypeSubstitutionMap InterfaceToArchetypeMap; + +public: + const TypeSubstitutionMap &getArchetypeToInterfaceMap() const { + return ArchetypeToInterfaceMap; + } + + const TypeSubstitutionMap &getInterfaceToArchetypeMap() const { + return InterfaceToArchetypeMap; + } + + explicit GenericEnvironment(TypeSubstitutionMap interfaceToArchetypeMap); + + static GenericEnvironment *get(ASTContext &ctx, + TypeSubstitutionMap interfaceToArchetypeMap); + + /// Make vanilla new/delete illegal. + void *operator new(size_t Bytes) = delete; + void operator delete(void *Data) = delete; + + /// Only allow allocation of GenericEnvironments using the allocator + /// in ASTContext. + void *operator new(size_t bytes, const ASTContext &ctx); + + /// Map a contextual type to an interface type. + Type mapTypeOutOfContext(ModuleDecl *M, Type type) const; + + /// Map an interface type to a contextual type. + Type mapTypeIntoContext(ModuleDecl *M, Type type) const; + + /// Derive a contextual type substitution map from a substitution array. + /// This is just like GenericSignature::getSubstitutionMap(), except + /// with contextual types instead of interface types. + void + getSubstitutionMap(ModuleDecl *mod, + GenericSignature *sig, + ArrayRef subs, + TypeSubstitutionMap &subsMap, + ArchetypeConformanceMap &conformanceMap) const; + + ArrayRef + getForwardingSubstitutions(ModuleDecl *M, GenericSignature *sig) const; +}; + +} // end namespace swift + +#endif // SWIFT_AST_GENERIC_ENVIRONMENT_H + diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 6cd223b01377d..9768dbd9ad7a7 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -184,10 +184,6 @@ class GenericSignature final : public llvm::FoldingSetNode, /// Return a range that iterates through first all of the generic parameters /// of the signature, followed by all of their recursive member types exposed /// through protocol requirements. - /// - /// The member types are presented in the - /// same order as GenericParamList::getAllArchetypes would present for an - /// equivalent GenericParamList. GenericSignatureWitnessIterator getAllDependentTypes() const { return GenericSignatureWitnessIterator(getRequirements()); } @@ -204,8 +200,10 @@ class GenericSignature final : public llvm::FoldingSetNode, /// for mangling purposes. /// /// TODO: This is what getCanonicalSignature() ought to do, but currently - /// cannot due to implementation dependencies on 'getAllDependentTypes' - /// order matching 'getAllArchetypes' order of a generic param list. + /// does not due to former implementation dependencies on + /// 'getAllDependentTypes' order matching 'getAllArchetypes' order of a + /// generic param list. Now that 'getAllArchetypes' is gone, we might + /// be able to move forward here. CanGenericSignature getCanonicalManglingSignature(ModuleDecl &M) const; /// Uniquing for the ASTContext. diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 40047ba3a4bca..54122e7dda58b 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -20,7 +20,7 @@ #include namespace swift { -class GenericParamList; +class GenericEnvironment; class CanType; class Decl; class ValueDecl; @@ -336,9 +336,8 @@ struct PrintOptions { /// formatting. bool PrintOriginalSourceText = false; - /// \brief Print dependent types as references into this generic parameter - /// list. - GenericParamList *ContextGenericParams = nullptr; + /// \brief Print dependent types as references into this generic environment. + GenericEnvironment *GenericEnv = nullptr; /// \brief Print types with alternative names from their canonical names. llvm::DenseMap *AlternativeTypeNames = nullptr; diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index 23963d23f136f..34e2b8759399c 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -236,10 +236,9 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance { /// Retrieve the complete set of protocol conformances for directly inherited /// protocols. const InheritedConformanceMap &getInheritedConformances() const; - + /// Get the generic parameters open on the conforming type. - /// FIXME: Retire in favor of getGenericSignature(). - GenericParamList *getGenericParams() const; + GenericEnvironment *getGenericEnvironment() const; /// Get the generic signature containing the parameters open on the conforming /// interface type. diff --git a/include/swift/AST/Substitution.h b/include/swift/AST/Substitution.h index bedcfa95405c8..c5c0717761363 100644 --- a/include/swift/AST/Substitution.h +++ b/include/swift/AST/Substitution.h @@ -26,6 +26,7 @@ namespace llvm { namespace swift { class ArchetypeType; + class GenericEnvironment; class ProtocolConformanceRef; /// DenseMap type used internally by Substitution::subst to track conformances @@ -63,11 +64,11 @@ class Substitution { /// conformances. /// /// Our replacement type must be written in terms of the context - /// archetypes of 'context', which in turn must be derived from the + /// archetypes of 'env', which in turn must be derived from the /// generic requirements of 'sig'. Substitution subst(ModuleDecl *module, GenericSignature *sig, - GenericParamList *context, + GenericEnvironment *env, ArrayRef subs) const; private: diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index c5a0d1e3b66f0..039b0ce931728 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -364,9 +364,10 @@ inline IdentTypeRepr::ComponentRange IdentTypeRepr::getComponentRange() { /// Foo -> Bar /// \endcode class FunctionTypeRepr : public TypeRepr { - // These two are only used in SIL mode, which is the only time + // These three are only used in SIL mode, which is the only time // we can have polymorphic function values. GenericParamList *GenericParams; + GenericEnvironment *GenericEnv; GenericSignature *GenericSig; TypeRepr *ArgsTy; @@ -378,12 +379,15 @@ class FunctionTypeRepr : public TypeRepr { FunctionTypeRepr(GenericParamList *genericParams, TypeRepr *argsTy, SourceLoc throwsLoc, SourceLoc arrowLoc, TypeRepr *retTy) : TypeRepr(TypeReprKind::Function), - GenericParams(genericParams), GenericSig(nullptr), + GenericParams(genericParams), + GenericEnv(nullptr), + GenericSig(nullptr), ArgsTy(argsTy), RetTy(retTy), ArrowLoc(arrowLoc), ThrowsLoc(throwsLoc) { } GenericParamList *getGenericParams() const { return GenericParams; } + GenericEnvironment *getGenericEnvironment() const { return GenericEnv; } GenericSignature *getGenericSignature() const { return GenericSig; } void setGenericSignature(GenericSignature *genericSig) { @@ -391,6 +395,11 @@ class FunctionTypeRepr : public TypeRepr { GenericSig = genericSig; } + void setGenericEnvironment(GenericEnvironment *genericEnv) { + assert(GenericEnv == nullptr); + GenericEnv = genericEnv; + } + TypeRepr *getArgsTypeRepr() const { return ArgsTy; } TypeRepr *getResultTypeRepr() const { return RetTy; } bool throws() const { return ThrowsLoc.isValid(); } diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 99321e7983775..ab93ee0abd893 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -92,7 +92,7 @@ class SILFunction CanSILFunctionType LoweredType; /// The context archetypes of the function. - GenericParamList *ContextGenericParams; + GenericEnvironment *GenericEnv; /// The forwarding substitutions, lazily computed. Optional> ForwardingSubs; @@ -178,7 +178,7 @@ class SILFunction SILFunction(SILModule &module, SILLinkage linkage, StringRef mangledName, CanSILFunctionType loweredType, - GenericParamList *contextGenericParams, + GenericEnvironment *genericEnv, Optional loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, @@ -192,7 +192,7 @@ class SILFunction static SILFunction *create(SILModule &M, SILLinkage linkage, StringRef name, CanSILFunctionType loweredType, - GenericParamList *contextGenericParams, + GenericEnvironment *genericEnv, Optional loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, @@ -545,16 +545,14 @@ class SILFunction return (ClangNodeOwner ? ClangNodeOwner->getClangDecl() : nullptr); } - /// Retrieve the generic parameter list containing the contextual archetypes - /// of the function. - /// - /// FIXME: We should remove this in favor of lazy archetype instantiation - /// using the 'getArchetype' and 'mapTypeIntoContext' interfaces. - GenericParamList *getContextGenericParams() const { - return ContextGenericParams; + /// Retrieve the generic environment containing the mapping from interface + /// types to context archetypes for this function. Only present if the + /// function has a body. + GenericEnvironment *getGenericEnvironment() const { + return GenericEnv; } - void setContextGenericParams(GenericParamList *params) { - ContextGenericParams = params; + void setGenericEnvironment(GenericEnvironment *env) { + GenericEnv = env; } /// Map the given type, which is based on an interface SILFunctionType and may diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index a5f41f8b005a6..cbc9c358e093d 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -480,7 +480,7 @@ class SILModule { /// SILModule. Eventually the uses should probably be refactored. SILFunction *createFunction( SILLinkage linkage, StringRef name, CanSILFunctionType loweredType, - GenericParamList *contextGenericParams, Optional loc, + GenericEnvironment *genericEnv, Optional loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, IsFragile_t isFragile, IsThunk_t isThunk = IsNotThunk, SILFunction::ClassVisibility_t classVisibility = SILFunction::NotRelevant, diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 368afef13b359..687ab87058546 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -366,16 +366,9 @@ struct SILConstantInfo { /// The SIL function type of the constant. CanSILFunctionType SILFnType; - /// The context generic parameters used by the constant. - /// This will be the innermost generic parameter list that applies to the - /// constant, which may be the generic parameter list of an enclosing context. - GenericParamList *ContextGenericParams; + /// The generic environment used by the constant. + GenericEnvironment *GenericEnv; - /// The generic parameter list of the function. - /// If the function does not have any generic parameters of its own, this - /// will be null. - GenericParamList *InnerGenericParams; - SILType getSILType() const { return SILType::getPrimitiveObjectType(SILFnType); } @@ -384,8 +377,7 @@ struct SILConstantInfo { return lhs.FormalInterfaceType == rhs.FormalInterfaceType && lhs.LoweredInterfaceType == rhs.LoweredInterfaceType && lhs.SILFnType == rhs.SILFnType && - lhs.ContextGenericParams == rhs.ContextGenericParams && - lhs.InnerGenericParams == rhs.InnerGenericParams; + lhs.GenericEnv == rhs.GenericEnv; } friend bool operator!=(SILConstantInfo lhs, SILConstantInfo rhs) { return !(lhs == rhs); @@ -521,11 +513,8 @@ class TypeConverter { CanAnyFunctionType makeConstantInterfaceType(SILDeclRef constant); - /// Get the context parameters for a constant. Returns a pair of the innermost - /// generic parameter list and the generic param list that directly applies - /// to the constant, if any. - std::pair - getConstantContextGenericParams(SILDeclRef constant); + /// Get the generic environment for a constant. + GenericEnvironment *getConstantGenericEnvironment(SILDeclRef constant); // Types converted during foreign bridging. #define BRIDGING_KNOWN_TYPE(BridgedModule,BridgedType) \ @@ -746,8 +735,8 @@ class TypeConverter { Type lvalueType); /// Retrieve the set of archetypes closed over by the given function. - GenericParamList *getEffectiveGenericParams(AnyFunctionRef fn, - CaptureInfo captureInfo); + GenericEnvironment *getEffectiveGenericEnvironment(AnyFunctionRef fn, + CaptureInfo captureInfo); /// Retrieve the set of generic parameters closed over by the given function. CanGenericSignature getEffectiveGenericSignature(AnyFunctionRef fn, diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h index 76ac61c020e0a..260704ace7825 100644 --- a/include/swift/SIL/TypeSubstCloner.h +++ b/include/swift/SIL/TypeSubstCloner.h @@ -90,9 +90,9 @@ class TypeSubstCloner : public SILClonerWithScopes { Substitution remapSubstitution(Substitution sub) { if (!ApplySubs.empty()) { - auto *params = Original.getContextGenericParams(); auto sig = Original.getLoweredFunctionType()->getGenericSignature(); - sub = sub.subst(SwiftMod, sig, params, ApplySubs); + auto *env = Original.getGenericEnvironment(); + sub = sub.subst(SwiftMod, sig, env, ApplySubs); } // Remap opened archetypes into the cloned context. return Substitution(getASTTypeInClonedContext(sub.getReplacement() @@ -209,9 +209,9 @@ class TypeSubstCloner : public SILClonerWithScopes { auto sub = Inst->getSelfSubstitution(); if (!ApplySubs.empty()) { auto sig = Original.getLoweredFunctionType()->getGenericSignature(); - auto *params = Original.getContextGenericParams(); + auto *env = Original.getGenericEnvironment(); sub = sub.subst(Inst->getModule().getSwiftModule(), - sig, params, ApplySubs); + sig, env, ApplySubs); } assert(sub.getConformances().size() == 1 && diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def index 6de1c6d165ae8..ff8cdd3c509f4 100644 --- a/include/swift/Serialization/DeclTypeRecordNodes.def +++ b/include/swift/Serialization/DeclTypeRecordNodes.def @@ -169,6 +169,7 @@ OTHER(GENERIC_PARAM_LIST, 240) TRAILING_INFO(GENERIC_PARAM) TRAILING_INFO(GENERIC_REQUIREMENT) TRAILING_INFO(LAST_GENERIC_REQUIREMENT) +TRAILING_INFO(GENERIC_ENVIRONMENT) OTHER(LOCAL_DISCRIMINATOR, 248) OTHER(PRIVATE_DISCRIMINATOR, 249) diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h index d3aeb007aa1d5..ba1ef5fa7340a 100644 --- a/include/swift/Serialization/ModuleFile.h +++ b/include/swift/Serialization/ModuleFile.h @@ -426,12 +426,36 @@ class ModuleFile : public LazyMemberLoader { ParameterList *readParameterList(); GenericParamList *maybeGetOrReadGenericParams(serialization::DeclID contextID, - DeclContext *DC, - llvm::BitstreamCursor &Cursor); + DeclContext *DC); + + /// Reads a generic param list from \c DeclTypeCursor. + /// + /// If the record at the cursor is not a generic param list, returns null + /// without moving the cursor. + GenericParamList *maybeReadGenericParams(DeclContext *DC, + GenericParamList *outerParams = nullptr); /// Reads a set of requirements from \c DeclTypeCursor. void readGenericRequirements(SmallVectorImpl &requirements); + /// Reads a GenericEnvironment from \c DeclTypeCursor. + /// + /// Also returns the set of generic parameters read, in order, to help with + /// forming a GenericSignature. + GenericEnvironment *readGenericEnvironment( + SmallVectorImpl ¶mTypes, + llvm::BitstreamCursor &Cursor); + + /// Reads a GenericEnvironment followed by requirements from \c DeclTypeCursor. + /// + /// Returns the GenericEnvironment and the signature formed from the + /// generic parameters of the environment, together with the + /// read requirements. + /// + /// Returns nullptr if there's no generic signature here. + std::pair + maybeReadGenericSignature(); + /// Populates the vector with members of a DeclContext from \c DeclTypeCursor. /// /// Returns true if there is an error. @@ -691,14 +715,6 @@ class ModuleFile : public LazyMemberLoader { NormalProtocolConformance * readNormalConformance(serialization::NormalConformanceID id); - /// Reads a generic param list from \c DeclTypeCursor. - /// - /// If the record at the cursor is not a generic param list, returns null - /// without moving the cursor. - GenericParamList *maybeReadGenericParams(DeclContext *DC, - llvm::BitstreamCursor &Cursor, - GenericParamList *outerParams = nullptr); - /// Reads a foreign error conformance from \c DeclTypeCursor, if present. Optional maybeReadForeignErrorConvention(); }; diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 2585dde4ef5a6..7c58975eb9471 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 = 261; // Last change: remove AllArchetypes indexing +const uint16_t VERSION_MINOR = 264; // Last change: remove AllArchetypes using DeclID = PointerEmbeddedInt; using DeclIDField = BCFixed<31>; @@ -1082,8 +1082,7 @@ namespace decls_block { >; using GenericParamListLayout = BCRecordLayout< - GENERIC_PARAM_LIST, - BCArray // Archetypes + GENERIC_PARAM_LIST // The actual parameters and requirements trail the record. >; @@ -1092,6 +1091,24 @@ namespace decls_block { DeclIDField // Typealias >; + // Subtlety here: GENERIC_ENVIRONMENT is serialized for both Decls and + // SILFunctions. + // + // For Decls, the interface type is non-canonical, so it points back + // to the GenericParamListDecl. This allows us to use the serialized + // GENERIC_ENVIRONMENT records to form the GenericSignature, as well. + // The type is canonicalized when forming the actual GenericEnvironment + // instance. + // + // For SILFunctions, the interface type below is always canonical, + // since SILFunctions never point back to any original + // GenericTypeParamDecls. + using GenericEnvironmentLayout = BCRecordLayout< + GENERIC_ENVIRONMENT, + TypeIDField, // interface type + TypeIDField // contextual type + >; + using GenericRequirementLayout = BCRecordLayout< GENERIC_REQUIREMENT, GenericRequirementKindField, // requirement kind diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 5f0d28eb1b206..151bafa250056 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -43,6 +43,7 @@ namespace swift { class DiagnosticConsumer; class DiagnosticEngine; class FileUnit; + class GenericEnvironment; class GenericParamList; class GenericSignature; class IRGenOptions; @@ -208,9 +209,10 @@ namespace swift { bool ProduceDiagnostics = true); /// Expose TypeChecker's handling of GenericParamList to SIL parsing. - GenericSignature *handleSILGenericParams(ASTContext &Ctx, - GenericParamList *genericParams, - DeclContext *DC); + std::pair + handleSILGenericParams(ASTContext &Ctx, + GenericParamList *genericParams, + DeclContext *DC); /// Turn the given module into SIL IR. /// diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7e2c040567aa8..c702ee2df25a3 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -24,6 +24,7 @@ #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" #include "swift/AST/LazyResolver.h" #include "swift/AST/ModuleLoader.h" @@ -3754,8 +3755,7 @@ void GenericSignature::Profile(llvm::FoldingSetNodeID &ID, GenericSignature *GenericSignature::get(ArrayRef params, ArrayRef requirements, bool isKnownCanonical) { - if (params.empty() && requirements.empty()) - return nullptr; + assert(!params.empty()); // Check for an existing generic signature. llvm::FoldingSetNodeID ID; @@ -3781,6 +3781,12 @@ GenericSignature *GenericSignature::get(ArrayRef params, return newSig; } +GenericEnvironment * +GenericEnvironment::get(ASTContext &ctx, + TypeSubstitutionMap interfaceToArchetypeMap) { + return new (ctx) GenericEnvironment(interfaceToArchetypeMap); +} + void DeclName::CompoundDeclName::Profile(llvm::FoldingSetNodeID &id, Identifier baseName, ArrayRef argumentNames) { diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 2905219a765ce..88d53106b3722 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -21,6 +21,7 @@ #include "swift/AST/Attr.h" #include "swift/AST/Decl.h" #include "swift/AST/Expr.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" #include "swift/AST/ParameterList.h" @@ -4274,25 +4275,14 @@ class TypePrinter : public TypeVisitor { } } - GenericParamList *getGenericParamListAtDepth(unsigned depth) { - assert(Options.ContextGenericParams); - if (!UnwrappedGenericParams) { - std::vector paramLists; - for (auto *params = Options.ContextGenericParams; - params; - params = params->getOuterParameters()) { - paramLists.push_back(params); - } - UnwrappedGenericParams = std::move(paramLists); - } - return UnwrappedGenericParams->rbegin()[depth]; - } - void visitGenericTypeParamType(GenericTypeParamType *T) { // Substitute a context archetype if we have context generic params. - if (Options.ContextGenericParams) { - return visit(getGenericParamListAtDepth(T->getDepth()) - ->getParams()[T->getIndex()]->getArchetype()); + if (Options.GenericEnv) { + auto *paramTy = T->getCanonicalType().getPointer(); + auto &map = Options.GenericEnv->getInterfaceToArchetypeMap(); + auto found = map.find(paramTy); + if (found != map.end()) + return visit(found->second); } auto Name = T->getName(); @@ -4483,18 +4473,11 @@ void TypeBase::print(ASTPrinter &Printer, const PrintOptions &PO) const { void ProtocolConformance::printName(llvm::raw_ostream &os, const PrintOptions &PO) const { if (getKind() == ProtocolConformanceKind::Normal) { - if (PO.PrintForSIL) { - if (auto genericSig = getGenericSignature()) { - StreamPrinter sPrinter(os); - TypePrinter typePrinter(sPrinter, PO); - typePrinter.printGenericSignature(genericSig->getGenericParams(), - genericSig->getRequirements()); - os << ' '; - } - } else if (auto gp = getGenericParams()) { - StreamPrinter SPrinter(os); - PrintAST Printer(SPrinter, PO); - Printer.printGenericParams(gp); + if (auto genericSig = getGenericSignature()) { + StreamPrinter sPrinter(os); + TypePrinter typePrinter(sPrinter, PO); + typePrinter.printGenericSignature(genericSig->getGenericParams(), + genericSig->getRequirements()); os << ' '; } } diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index f83926c885235..cc14d5d9e0a94 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -20,6 +20,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/ForeignErrorConvention.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Mangle.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/Basic/SourceManager.h" @@ -1957,7 +1958,44 @@ struct ASTNodeBase {}; } } } - + + void verifyGenericEnvironment(Decl *D, + GenericSignature *sig, + GenericEnvironment *env) { + if (!sig && !env) + return; + + if (sig && env) { + auto &map = env->getInterfaceToArchetypeMap(); + if (sig->getGenericParams().size() != map.size()) { + Out << "Mismatch between signature and environment parameter count\n"; + abort(); + } + + for (auto *paramTy : sig->getGenericParams()) { + auto found = map.find(paramTy->getCanonicalType().getPointer()); + if (found == map.end()) { + Out << "Generic parameter present in signature but not " + "in environment\n"; + paramTy->dump(); + abort(); + } + } + + return; + } + + Out << "Decl must have both signature and environment, or neither\n"; + D->dump(Out); + abort(); + } + + void verifyChecked(GenericTypeDecl *generic) { + verifyGenericEnvironment(generic, + generic->getGenericSignature(), + generic->getGenericEnvironment()); + } + void verifyChecked(NominalTypeDecl *nominal) { // Make sure that the protocol list is fully expanded. verifyProtocolList(nominal, nominal->getLocalProtocols()); @@ -2084,195 +2122,6 @@ struct ASTNodeBase {}; verifyParsedBase(DD); } - bool checkAllArchetypes(const GenericParamList *generics) { - ArrayRef storedArchetypes = generics->getAllArchetypes(); - - SmallVector derivedBuffer; - ArrayRef derivedArchetypes = - GenericParamList::deriveAllArchetypes(generics->getParams(), - derivedBuffer); - - return (storedArchetypes == derivedArchetypes); - } - - /// Check that the generic requirements line up with the archetypes. - void checkGenericRequirements(Decl *decl, - DeclContext *dc, - GenericFunctionType *genericTy) { - - PrettyStackTraceDecl debugStack("verifying generic requirements", decl); - - // We need to have generic parameters here. - auto genericParams = dc->getGenericParamsOfContext(); - if (!genericParams) { - Out << "Missing generic parameters\n"; - decl->dump(Out); - abort(); - } - - // Verify that the list of all archetypes matches what we would - // derive from the generic params. - if (!checkAllArchetypes(genericParams)) { - Out << "Archetypes list in generic parameter list doesn't " - "match what would have been derived\n"; - decl->dump(Out); - abort(); - } - - // Step through the list of requirements in the generic type. - auto requirements = genericTy->getRequirements(); - - // Skip over same-type requirements. - auto skipUnrepresentedRequirements = [&]() { - for (; !requirements.empty(); requirements = requirements.slice(1)) { - bool done = false; - switch (requirements.front().getKind()) { - case RequirementKind::Conformance: - // If the second type is a protocol type, we're done. - done = true; - break; - - case RequirementKind::Superclass: - break; - - case RequirementKind::SameType: - // Skip the next same-type constraint. - continue; - - case RequirementKind::WitnessMarker: - done = true; - break; - } - - if (done) - break; - } - }; - skipUnrepresentedRequirements(); - - // Collect all of the generic parameter lists. - SmallVector allGenericParamLists; - for (auto gpList = genericParams; gpList; - gpList = gpList->getOuterParameters()) { - allGenericParamLists.push_back(gpList); - } - std::reverse(allGenericParamLists.begin(), allGenericParamLists.end()); - - // Helpers that diagnose failures when generic requirements mismatch. - bool failed = false; - auto noteFailure =[&]() { - if (failed) - return; - - Out << "Generic requirements don't match all archetypes\n"; - decl->dump(Out); - - Out << "\nGeneric type: " << genericTy->getString() << "\n"; - Out << "Expected requirements: "; - bool first = true; - for (auto gpList : allGenericParamLists) { - for (auto archetype : gpList->getAllArchetypes()) { - for (auto proto : archetype->getConformsTo()) { - if (first) - first = false; - else - Out << ", "; - - Out << archetype->getString() << " : " - << proto->getDeclaredType()->getString(); - } - } - } - Out << "\n"; - - failed = true; - }; - - // Walk through all of the archetypes in the generic parameter lists, - // matching up their conformance requirements with those in the - for (auto gpList : allGenericParamLists) { - for (auto archetype : gpList->getAllArchetypes()) { - // Make sure we have the value witness marker. - if (requirements.empty()) { - noteFailure(); - Out << "Ran out of requirements before we ran out of archetypes\n"; - break; - } - - if (requirements.front().getKind() - == RequirementKind::WitnessMarker) { - auto type = ArchetypeBuilder::mapTypeIntoContext( - dc, - requirements.front().getFirstType()); - if (type->isEqual(archetype)) { - requirements = requirements.slice(1); - skipUnrepresentedRequirements(); - } else { - noteFailure(); - Out << "Value witness marker for " << type->getString() - << " does not match expected " << archetype->getString() - << "\n"; - } - } else { - noteFailure(); - Out << "Missing value witness marker for " - << archetype->getString() << "\n"; - } - - for (auto proto : archetype->getConformsTo()) { - // If there are no requirements left, we're missing requirements. - if (requirements.empty()) { - noteFailure(); - Out << "No requirement for " << archetype->getString() - << " : " << proto->getDeclaredType()->getString() << "\n"; - continue; - } - - auto firstReqType = ArchetypeBuilder::mapTypeIntoContext( - dc, - requirements.front().getFirstType()); - auto secondReqType = ArchetypeBuilder::mapTypeIntoContext( - dc, - requirements.front().getSecondType()); - - // If the requirements match up, move on to the next requirement. - if (firstReqType->isEqual(archetype) && - secondReqType->isEqual(proto->getDeclaredType())) { - requirements = requirements.slice(1); - skipUnrepresentedRequirements(); - continue; - } - - noteFailure(); - - // If the requirements don't match up, complain. - if (!firstReqType->isEqual(archetype)) { - Out << "Mapped archetype " << firstReqType->getString() - << " does not match expected " << archetype->getString() - << "\n"; - continue; - } - - Out << "Mapped conformance " << secondReqType->getString() - << " does not match expected " - << proto->getDeclaredType()->getString() << "\n"; - } - } - } - - if (!requirements.empty()) { - noteFailure(); - Out << "Extra requirement " - << requirements.front().getFirstType()->getString() - << " : " - << requirements.front().getSecondType()->getString() - << "\n"; - } - - if (failed) - abort(); - } - void verifyChecked(AbstractFunctionDecl *AFD) { PrettyStackTraceDecl debugStack("verifying AbstractFunctionDecl", AFD); @@ -2326,6 +2175,10 @@ struct ASTNodeBase {}; abort(); } + verifyGenericEnvironment(AFD, + AFD->getGenericSignature(), + AFD->getGenericEnvironment()); + // If there is an interface type, it shouldn't have any unresolved // dependent member types. // FIXME: This is a general property of the type system. @@ -2347,12 +2200,6 @@ struct ASTNodeBase {}; abort(); } - // If the interface type is generic, make sure its requirements - // line up with the archetypes. - if (auto genericTy = interfaceTy->getAs()) { - checkGenericRequirements(AFD, AFD, genericTy); - } - // Throwing @objc methods must have a foreign error convention. if (AFD->isObjC() && static_cast(AFD->getForeignErrorConvention()) diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index d468d85c0dadb..f21f4e60dcc50 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -20,6 +20,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/DiagnosticEngine.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" @@ -169,11 +170,6 @@ struct ArchetypeBuilder::Implementation { /// archetypes. llvm::MapVector PotentialArchetypes; - /// A vector containing all of the archetypes, expanded out. - /// FIXME: This notion should go away, because it's impossible to expand - /// out "all" archetypes - SmallVector AllArchetypes; - /// A vector containing the same-type requirements introduced into the /// system. SmallVector SameTypeRequirements; @@ -1765,41 +1761,6 @@ ArchetypeBuilder::getArchetype(GenericTypeParamDecl *GenericParam) { return known->second->getType(*this).getAsArchetype(); } -ArrayRef ArchetypeBuilder::getAllArchetypes() { - // This should be kept in sync with GenericParamList::deriveAllArchetypes(). - if (Impl->AllArchetypes.empty()) { - // Collect the primary archetypes first. - unsigned depth = Impl->PotentialArchetypes.back().first.Depth; - llvm::SmallPtrSet KnownArchetypes; - for (const auto &Entry : Impl->PotentialArchetypes) { - // Skip outer potential archetypes. - if (Entry.first.Depth < depth) - continue; - - PotentialArchetype *PA = Entry.second; - auto Archetype = PA->getType(*this).castToArchetype(); - if (KnownArchetypes.insert(Archetype).second) - Impl->AllArchetypes.push_back(Archetype); - } - - // Collect all of the remaining archetypes. - for (const auto &Entry : Impl->PotentialArchetypes) { - // Skip outer potential archetypes. - if (Entry.first.Depth < depth) - continue; - - PotentialArchetype *PA = Entry.second; - if (!PA->isConcreteType() && !PA->getTypeAliasDecl()) { - auto Archetype = PA->getType(*this).castToArchetype(); - GenericParamList::addNestedArchetypes(Archetype, KnownArchetypes, - Impl->AllArchetypes); - } - } - } - - return Impl->AllArchetypes; -} - ArrayRef ArchetypeBuilder::getSameTypeRequirements() const { return Impl->SameTypeRequirements; @@ -2010,88 +1971,44 @@ void ArchetypeBuilder::dump(llvm::raw_ostream &out) { out << "\n"; } -Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type, - LazyResolver *resolver) { - auto genericParams = dc->getGenericParamsOfContext(); - return mapTypeIntoContext(dc->getParentModule(), genericParams, type, - resolver); +Type ArchetypeBuilder::mapTypeIntoContext(const DeclContext *dc, Type type) { + return mapTypeIntoContext(dc->getParentModule(), + dc->getGenericEnvironmentOfContext(), + type); } -Type ArchetypeBuilder::mapTypeIntoContext(Module *M, - GenericParamList *genericParams, - Type type, - LazyResolver *resolver) { +Type ArchetypeBuilder::mapTypeIntoContext(ModuleDecl *M, + GenericEnvironment *env, + Type type) { auto canType = type->getCanonicalType(); assert(!canType->hasArchetype() && "already have a contextual type"); if (!canType->hasTypeParameter()) return type; - assert(genericParams && "dependent type in non-generic context"); - - unsigned genericParamsDepth = genericParams->getDepth(); - type = type.transform([&](Type type) -> Type { - // Map a generic parameter type to its archetype. - if (auto gpType = type->getAs()) { - auto index = gpType->getIndex(); - unsigned depth = gpType->getDepth(); - - // Skip down to the generic parameter list that houses the corresponding - // generic parameter. - auto myGenericParams = genericParams; - assert(genericParamsDepth >= depth); - unsigned skipLevels = genericParamsDepth - depth; - while (skipLevels > 0) { - myGenericParams = myGenericParams->getOuterParameters(); - assert(myGenericParams && "Wrong number of levels?"); - --skipLevels; - } - - return myGenericParams->getParams()[index]->getArchetype(); - } - - // Map a dependent member to the corresponding nested archetype. - if (auto dependentMember = type->getAs()) { - auto base = mapTypeIntoContext(M, genericParams, - dependentMember->getBase(), resolver); - return dependentMember->substBaseType(M, base, resolver); - } + assert(env && "dependent type in non-generic context"); - return type; - }); - - assert(!type->hasTypeParameter() && "not fully substituted"); - return type; + return env->mapTypeIntoContext(M, type); } Type ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) { - GenericParamList *genericParams = dc->getGenericParamsOfContext(); - return mapTypeOutOfContext(dc->getParentModule(), genericParams, type); + return mapTypeOutOfContext(dc->getParentModule(), + dc->getGenericEnvironmentOfContext(), + type); } -Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, - GenericParamList *genericParams, - Type type) { +Type +ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, + GenericEnvironment *env, + Type type) { auto canType = type->getCanonicalType(); assert(!canType->hasTypeParameter() && "already have an interface type"); if (!canType->hasArchetype()) return type; - assert(genericParams && "dependent type in non-generic context"); + assert(env && "dependent type in non-generic context"); - // Capture the archetype -> interface type mapping. - TypeSubstitutionMap subs; - for (auto params = genericParams; params != nullptr; - params = params->getOuterParameters()) { - for (auto param : *params) { - subs[param->getArchetype()] = param->getDeclaredType(); - } - } - - type = type.subst(M, subs, SubstFlags::AllowLoweredTypes); - - assert(!type->hasArchetype() && "not fully substituted"); - return type; + return env->mapTypeOutOfContext(M, type); } void ArchetypeBuilder::addGenericSignature(GenericSignature *sig, @@ -2213,6 +2130,10 @@ addNestedRequirements( auto nestedType = rep->getDependentType(builder, /*allowUnresolved*/ false); + // Skip unresolved nested types. + if (nestedType->is()) + continue; + addRequirements(builder, nestedType, rep, knownPAs, requirements); addNestedRequirements(builder, rep, knownPAs, requirements); } @@ -2303,3 +2224,25 @@ GenericSignature *ArchetypeBuilder::getGenericSignature( return sig; } +GenericEnvironment *ArchetypeBuilder::getGenericEnvironment( + ArrayRef genericParamTypes) { + TypeSubstitutionMap interfaceToArchetypeMap; + + for (auto paramTy : genericParamTypes) { + auto known = Impl->PotentialArchetypes.find( + GenericTypeParamKey::forType(paramTy)); + assert(known != Impl->PotentialArchetypes.end()); + + auto archetypeTy = known->second->getType(*this).getAsArchetype(); + auto concreteTy = known->second->getType(*this).getAsConcreteType(); + if (archetypeTy) + interfaceToArchetypeMap[paramTy] = archetypeTy; + else if (concreteTy) + interfaceToArchetypeMap[paramTy] = concreteTy; + else + llvm_unreachable("broken generic parameter"); + } + + return GenericEnvironment::get(Context, interfaceToArchetypeMap); +} + diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index 6ce7b3001d880..2b0497597b39d 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -14,8 +14,9 @@ // //===----------------------------------------------------------------------===// -#include "swift/AST/Builtins.h" #include "swift/AST/AST.h" +#include "swift/AST/Builtins.h" +#include "swift/AST/GenericEnvironment.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/Attributes.h" @@ -182,7 +183,7 @@ getBuiltinGenericFunction(Identifier Id, Type ResType, Type ResBodyType, GenericParamList *GenericParams, - FunctionType::ExtInfo Info = FunctionType::ExtInfo()){ + TypeSubstitutionMap InterfaceToArchetypeMap) { assert(GenericParams && "Missing generic parameters"); auto &Context = ResType->getASTContext(); @@ -200,11 +201,13 @@ getBuiltinGenericFunction(Identifier Id, requirements.push_back(Requirement(RequirementKind::WitnessMarker, param, Type())); } - GenericSignature *Sig = GenericSignature::get(GenericParamTypes,requirements); - - Type InterfaceType = GenericFunctionType::get(Sig, - ArgParamType, ResType, - Info); + GenericSignature *Sig = + GenericSignature::get(GenericParamTypes, requirements); + GenericEnvironment *Env = + GenericEnvironment::get(Context, InterfaceToArchetypeMap); + + Type InterfaceType = GenericFunctionType::get(Sig, ArgParamType, ResType, + AnyFunctionType::ExtInfo()); Module *M = Context.TheBuiltinModule; DeclContext *DC = &M->getMainFile(FileUnitKind::Builtin); @@ -223,7 +226,8 @@ getBuiltinGenericFunction(Identifier Id, // Compute the function type. Type FnType = PolymorphicFunctionType::get(paramList->getType(Context), - ResBodyType, GenericParams, Info); + ResBodyType, GenericParams, + AnyFunctionType::ExtInfo()); DeclName Name(Context, Id, paramList); auto func = FuncDecl::create(Context, /*StaticLoc=*/SourceLoc(), @@ -237,6 +241,7 @@ getBuiltinGenericFunction(Identifier Id, func->setInterfaceType(InterfaceType); func->setGenericSignature(Sig); + func->setGenericEnvironment(Env); func->setImplicit(); func->setAccessibility(Accessibility::Public); @@ -435,7 +440,7 @@ createGenericParam(ASTContext &ctx, const char *name, unsigned index) { new (ctx) GenericTypeParamDecl(&M->getMainFile(FileUnitKind::Builtin), ident, SourceLoc(), 0, index); genericParam->setArchetype(archetype); - return { archetype, genericParam }; + return std::make_pair(archetype, genericParam); } /// Create a generic parameter list with multiple generic parameters. @@ -444,7 +449,7 @@ static GenericParamList *getGenericParams(ASTContext &ctx, SmallVectorImpl &archetypes, SmallVectorImpl &genericParams) { assert(numParameters <= llvm::array_lengthof(GenericParamNames)); - assert(archetypes.empty() && genericParams.empty()); + assert(genericParams.empty()); for (unsigned i = 0; i != numParameters; ++i) { auto archetypeAndParam = createGenericParam(ctx, GenericParamNames[i], i); @@ -454,7 +459,6 @@ static GenericParamList *getGenericParams(ASTContext &ctx, auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams, SourceLoc()); - paramList->setAllArchetypes(ctx.AllocateCopy(archetypes)); return paramList; } @@ -469,6 +473,8 @@ namespace { SmallVector GenericTypeParams; SmallVector Archetypes; + TypeSubstitutionMap InterfaceToArchetypeMap; + SmallVector InterfaceParams; SmallVector BodyParams; @@ -480,6 +486,12 @@ namespace { : Context(ctx) { TheGenericParamList = getGenericParams(ctx, numGenericParams, Archetypes, GenericTypeParams); + + for (unsigned i = 0, e = GenericTypeParams.size(); i < e; i++) { + auto paramTy = GenericTypeParams[i]->getDeclaredType() + ->getCanonicalType().getPointer(); + InterfaceToArchetypeMap[paramTy] = Archetypes[i]; + } } template @@ -497,7 +509,8 @@ namespace { ValueDecl *build(Identifier name) { return getBuiltinGenericFunction(name, InterfaceParams, BodyParams, InterfaceResult, BodyResult, - TheGenericParamList); + TheGenericParamList, + InterfaceToArchetypeMap); } // Don't use these generator classes directly; call the make{...} diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 0bd0b8505d583..caf1838a82ee2 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -21,6 +21,7 @@ add_swift_library(swiftAST STATIC DiagnosticList.cpp DocComment.cpp Expr.cpp + GenericEnvironment.cpp GenericSignature.cpp Identifier.cpp LookupVisibleDecls.cpp diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3c2cd9dda2e30..e10852799cd53 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -536,81 +536,6 @@ void GenericParamList::addTrailingWhereClause( Requirements = newRequirements; } -void GenericParamList:: -getForwardingSubstitutionMap(TypeSubstitutionMap &result) const { - // Add forwarding substitutions from the outer context if we have - // a type nested inside a generic function. - for (auto *params = this; - params != nullptr; - params = params->getOuterParameters()) { - for (auto *param : params->getParams()) - result[param->getDeclaredType()->getCanonicalType().getPointer()] - = param->getArchetype(); - } -} - -ArrayRef -GenericParamList::getForwardingSubstitutions(GenericSignature *sig) const { - // This is stupid. We don't really need a module, because we - // should not be looking up concrete conformances when we - // substitute types here. - auto *mod = getParams()[0]->getDeclContext()->getParentModule(); - - TypeSubstitutionMap subs; - getForwardingSubstitutionMap(subs); - - auto lookupConformanceFn = - [&](Type replacement, ProtocolType *protoType) - -> ProtocolConformanceRef { - return ProtocolConformanceRef(protoType->getDecl()); - }; - - SmallVector result; - sig->getSubstitutions(*mod, subs, lookupConformanceFn, result); - return sig->getASTContext().AllocateCopy(result); -} - -/// \brief Add the nested archetypes of the given archetype to the set -/// of all archetypes. -void GenericParamList::addNestedArchetypes(ArchetypeType *archetype, - SmallPtrSetImpl &known, - SmallVectorImpl &all) { - for (auto nested : archetype->getNestedTypes()) { - auto nestedArch = nested.second.getAsArchetype(); - if (!nestedArch) - continue; - if (known.insert(nestedArch).second) { - assert(!nestedArch->isPrimary() && "Unexpected primary archetype"); - all.push_back(nestedArch); - addNestedArchetypes(nestedArch, known, all); - } - } -} - -ArrayRef -GenericParamList::deriveAllArchetypes(ArrayRef params, - SmallVectorImpl &all) { - // This should be kept in sync with ArchetypeBuilder::getAllArchetypes(). - - assert(all.empty()); - llvm::SmallPtrSet known; - - // Collect all the primary archetypes. - for (auto param : params) { - auto archetype = param->getArchetype(); - if (known.insert(archetype).second) - all.push_back(archetype); - } - - // Collect all the nested archetypes. - for (auto param : params) { - auto archetype = param->getArchetype(); - addNestedArchetypes(archetype, known, all); - } - - return all; -} - TrailingWhereClause::TrailingWhereClause( SourceLoc whereLoc, ArrayRef requirements) @@ -818,11 +743,6 @@ void ExtensionDecl::setGenericParams(GenericParamList *params) { } } -void ExtensionDecl::setGenericSignature(GenericSignature *sig) { - assert(!GenericSig && "Already have generic signature"); - GenericSig = sig; -} - DeclRange ExtensionDecl::getMembers() const { loadAllMembers(); return IterableDeclContext::getMembers(); @@ -2216,11 +2136,6 @@ void GenericTypeDecl::setGenericParams(GenericParamList *params) { Param->setDeclContext(this); } -void GenericTypeDecl::setGenericSignature(GenericSignature *sig) { - assert(!GenericSig && "Already have generic signature"); - GenericSig = sig; -} - TypeAliasDecl::TypeAliasDecl(SourceLoc TypeAliasLoc, Identifier Name, SourceLoc NameLoc, TypeLoc UnderlyingTy, diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index abef65f53799e..dcce0521d7740 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -257,6 +257,47 @@ GenericSignature *DeclContext::getGenericSignatureOfContext() const { } } +GenericEnvironment *DeclContext::getGenericEnvironmentOfContext() const { + for (const DeclContext *dc = this; ; dc = dc->getParent()) { + switch (dc->getContextKind()) { + case DeclContextKind::Module: + case DeclContextKind::FileUnit: + case DeclContextKind::TopLevelCodeDecl: + return nullptr; + + case DeclContextKind::Initializer: + case DeclContextKind::SerializedLocal: + case DeclContextKind::AbstractClosureExpr: + case DeclContextKind::SubscriptDecl: + // Closures and initializers can't themselves be generic, but they + // can occur in generic contexts. + continue; + + case DeclContextKind::AbstractFunctionDecl: { + auto *AFD = cast(dc); + if (auto genericCtx = AFD->getGenericEnvironment()) + return genericCtx; + continue; + } + + case DeclContextKind::GenericTypeDecl: { + auto GTD = cast(dc); + if (auto genericCtx = GTD->getGenericEnvironment()) + return genericCtx; + continue; + } + + case DeclContextKind::ExtensionDecl: { + auto ED = cast(dc); + if (auto genericCtx = ED->getGenericEnvironment()) + return genericCtx; + continue; + } + } + llvm_unreachable("bad DeclContextKind"); + } +} + DeclContext *DeclContext::getLocalContext() { if (isLocalContext()) return this; diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp new file mode 100644 index 0000000000000..e13b02c7c284d --- /dev/null +++ b/lib/AST/GenericEnvironment.cpp @@ -0,0 +1,105 @@ +//===--- GenericEnvironment.h - GenericEnvironment AST --------------------===// +// +// 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 implements the GenericEnvironment class. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ASTContext.h" +#include "swift/AST/GenericEnvironment.h" + +using namespace swift; + +GenericEnvironment::GenericEnvironment( + TypeSubstitutionMap interfaceToArchetypeMap) { + + assert(!interfaceToArchetypeMap.empty()); + + // Build a mapping in both directions, making sure to canonicalize the + // interface type where it is used as a key, so that substitution can + // find them, and to preserve sugar otherwise, so that + // mapTypeOutOfContext() produces a human-readable type. + for (auto entry : interfaceToArchetypeMap) { + // We're going to pass InterfaceToArchetypeMap to Type::subst(), which + // expects the keys to be canonical, otherwise it won't be able to + // find them. + auto canParamTy = cast(entry.first->getCanonicalType()); + auto contextTy = entry.second; + + auto result = InterfaceToArchetypeMap.insert( + std::make_pair(canParamTy, contextTy)); + assert(result.second && "duplicate generic parameters in environment"); + + // If we mapped the generic parameter to an archetype, add it to the + // reverse mapping. + if (auto *archetypeTy = entry.second->getAs()) + ArchetypeToInterfaceMap[archetypeTy] = entry.first; + + // FIXME: If multiple generic parameters map to the same archetype, + // the reverse mapping order is not deterministic. + } +} + +void *GenericEnvironment::operator new(size_t bytes, const ASTContext &ctx) { + return ctx.Allocate(bytes, alignof(GenericEnvironment), AllocationArena::Permanent); +} + +Type GenericEnvironment::mapTypeOutOfContext(ModuleDecl *M, Type type) const { + type = type.subst(M, ArchetypeToInterfaceMap, SubstFlags::AllowLoweredTypes); + assert(!type->hasArchetype() && "not fully substituted"); + return type; +} + +Type GenericEnvironment::mapTypeIntoContext(ModuleDecl *M, Type type) const { + type = type.subst(M, InterfaceToArchetypeMap, SubstFlags::AllowLoweredTypes); + assert(!type->hasTypeParameter() && "not fully substituted"); + return type; +} + +ArrayRef +GenericEnvironment::getForwardingSubstitutions( + ModuleDecl *M, GenericSignature *sig) const { + auto lookupConformanceFn = + [&](Type replacement, ProtocolType *protoType) + -> ProtocolConformanceRef { + return ProtocolConformanceRef(protoType->getDecl()); + }; + + SmallVector result; + sig->getSubstitutions(*M, InterfaceToArchetypeMap, + lookupConformanceFn, result); + return sig->getASTContext().AllocateCopy(result); +} + +void GenericEnvironment:: +getSubstitutionMap(ModuleDecl *mod, + GenericSignature *sig, + ArrayRef subs, + TypeSubstitutionMap &subsMap, + ArchetypeConformanceMap &conformanceMap) const { + + for (auto depTy : sig->getAllDependentTypes()) { + + // Map the interface type to a context type. + auto contextTy = depTy.subst(mod, InterfaceToArchetypeMap, SubstOptions()); + auto *archetype = contextTy->castTo(); + + auto sub = subs.front(); + subs = subs.slice(1); + + // Record the replacement type and its conformances. + subsMap[archetype] = sub.getReplacement(); + conformanceMap[archetype] = sub.getConformances(); + } + + assert(subs.empty() && "did not use all substitutions?!"); +} diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 09c5395606b13..b3d85ae513b2a 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -13,11 +13,13 @@ // This file implements the GenericSignature class. // //===----------------------------------------------------------------------===// + #include "swift/AST/GenericSignature.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" #include "swift/AST/Module.h" #include "swift/AST/Types.h" + using namespace swift; GenericSignature::GenericSignature(ArrayRef params, diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 1cb13318b4bcf..5f94d05ecfcea 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -19,6 +19,7 @@ #include "swift/AST/ASTPrinter.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/DiagnosticsSema.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/LazyResolver.h" #include "swift/AST/LinkLibrary.h" #include "swift/AST/ModuleLoader.h" @@ -587,16 +588,15 @@ TypeBase::gatherAllSubstitutions(Module *module, auto *parentDC = gpContext; while (parent) { if (auto boundGeneric = dyn_cast(parent)) { - auto genericParams = parentDC->getGenericParamsOfContext(); + auto genericSig = parentDC->getGenericSignatureOfContext(); unsigned index = 0; assert(boundGeneric->getGenericArgs().size() == - genericParams->getParams().size()); + genericSig->getInnermostGenericParams().size()); for (Type arg : boundGeneric->getGenericArgs()) { - auto gp = genericParams->getParams()[index++]; - substitutions[gp->getDeclaredType()->getCanonicalType() - .getPointer()] = arg; + auto paramTy = genericSig->getInnermostGenericParams()[index++]; + substitutions[paramTy->getCanonicalType().getPointer()] = arg; } parent = CanType(boundGeneric->getParent()); @@ -615,8 +615,11 @@ TypeBase::gatherAllSubstitutions(Module *module, // Add forwarding substitutions from the outer context if we have // a type nested inside a generic function. - if (auto *outerParams = parentDC->getGenericParamsOfContext()) - outerParams->getForwardingSubstitutionMap(substitutions); + if (auto *outerEnv = parentDC->getGenericEnvironmentOfContext()) + for (auto pair : outerEnv->getInterfaceToArchetypeMap()) { + auto result = substitutions.insert(pair); + assert(result.second); + } auto lookupConformanceFn = [&](Type replacement, ProtocolType *protoType) diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index c9083f2df1939..37555cf13e118 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -18,6 +18,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" #include "swift/AST/LazyResolver.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/Substitution.h" @@ -180,18 +181,20 @@ usesDefaultDefinition(AssociatedTypeDecl *requirement) const { CONFORMANCE_SUBCLASS_DISPATCH(usesDefaultDefinition, (requirement)) } -GenericParamList *ProtocolConformance::getGenericParams() const { +GenericEnvironment *ProtocolConformance::getGenericEnvironment() const { switch (getKind()) { case ProtocolConformanceKind::Inherited: case ProtocolConformanceKind::Normal: // If we have a normal or inherited protocol conformance, look for its // generic parameters. - return getDeclContext()->getGenericParamsOfContext(); + return getDeclContext()->getGenericEnvironmentOfContext(); case ProtocolConformanceKind::Specialized: // If we have a specialized protocol conformance, since we do not support // currently partial specialization, we know that it cannot have any open // type variables. + // + // FIXME: We could return a meaningful GenericEnvironment here return nullptr; } } @@ -354,7 +357,7 @@ SpecializedProtocolConformance::getTypeWitnessSubstAndDecl( auto conformingDC = getDeclContext(); auto conformingModule = conformingDC->getParentModule(); - auto *genericParams = GenericConformance->getGenericParams(); + auto *genericEnv = GenericConformance->getGenericEnvironment(); auto *genericSig = GenericConformance->getGenericSignature(); TypeSubstitutionMap substitutionMap; @@ -366,10 +369,10 @@ SpecializedProtocolConformance::getTypeWitnessSubstAndDecl( // Compute a context type substitution map from the // substitution array stored in this conformance - genericParams->getSubstitutionMap(conformingModule, genericSig, - GenericSubstitutions, - substitutionMap, - conformanceMap); + genericEnv->getSubstitutionMap(conformingModule, genericSig, + GenericSubstitutions, + substitutionMap, + conformanceMap); auto genericWitnessAndDecl = GenericConformance->getTypeWitnessSubstAndDecl(assocType, resolver); @@ -523,10 +526,10 @@ ProtocolConformance::getInheritedConformance(ProtocolDecl *protocol) const { auto *conformingModule = conformingDC->getParentModule(); auto *sig = conformingDC->getGenericSignatureOfContext(); - auto *params = conformingDC->getGenericParamsOfContext(); + auto *env = conformingDC->getGenericEnvironmentOfContext(); - params->getSubstitutionMap(conformingModule, sig, subs, - subMap, conformanceMap); + env->getSubstitutionMap(conformingModule, sig, subs, + subMap, conformanceMap); auto r = inherited->subst(conformingModule, getType(), subs, subMap, conformanceMap); diff --git a/lib/AST/Substitution.cpp b/lib/AST/Substitution.cpp index 598c57f2a77fd..2e2b92b28a444 100644 --- a/lib/AST/Substitution.cpp +++ b/lib/AST/Substitution.cpp @@ -17,6 +17,7 @@ #include "swift/AST/Substitution.h" #include "swift/AST/ASTContext.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/Types.h" #include "llvm/ADT/DenseMap.h" @@ -42,13 +43,13 @@ Substitution::Substitution(Type Replacement, Substitution Substitution::subst(Module *module, GenericSignature *sig, - GenericParamList *context, + GenericEnvironment *env, ArrayRef subs) const { TypeSubstitutionMap subMap; ArchetypeConformanceMap conformanceMap; - assert(sig && context); - context->getSubstitutionMap(module, sig, subs, subMap, conformanceMap); + assert(sig && env); + env->getSubstitutionMap(module, sig, subs, subMap, conformanceMap); return subst(module, subs, subMap, conformanceMap); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index e10a0be1d7380..9706fab221802 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2767,34 +2767,6 @@ PolymorphicFunctionType::getGenericParameters() const { return Params->getParams(); } -void GenericParamList:: -getSubstitutionMap(ModuleDecl *mod, - GenericSignature *sig, - ArrayRef subs, - TypeSubstitutionMap &subsMap, - ArchetypeConformanceMap &conformanceMap) const { - - // Map from interface types to archetypes - TypeSubstitutionMap map; - getForwardingSubstitutionMap(map); - - for (auto depTy : sig->getAllDependentTypes()) { - - // Map the interface type to a context type. - auto contextTy = depTy.subst(mod, map, SubstOptions()); - auto *archetype = contextTy->castTo(); - - auto sub = subs.front(); - subs = subs.slice(1); - - // Record the replacement type and its conformances. - subsMap[archetype] = sub.getReplacement(); - conformanceMap[archetype] = sub.getConformances(); - } - - assert(subs.empty() && "did not use all substitutions?!"); -} - FunctionType * GenericFunctionType::substGenericArgs(Module *M, ArrayRef args) { auto params = getGenericParams(); @@ -3489,8 +3461,6 @@ case TypeKind::Id: anyChanges = true; } - auto sig = GenericSignature::get(genericParams, requirements); - // Transform input type. auto inputTy = function->getInput().transform(fn); if (!inputTy) @@ -3508,11 +3478,12 @@ case TypeKind::Id: return *this; // If no generic parameters remain, this is a non-generic function type. - if (genericParams.empty()) + if (genericParams.empty()) { return FunctionType::get(inputTy, resultTy, function->getExtInfo()); + } // Produce the new generic function type. - + auto sig = GenericSignature::get(genericParams, requirements); return GenericFunctionType::get(sig, inputTy, resultTy, function->getExtInfo()); } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index ab6dab441aa02..e5added17b282 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -23,6 +23,8 @@ #include "swift/AST/Decl.h" #include "swift/AST/DiagnosticsClangImporter.h" #include "swift/AST/Expr.h" +#include "swift/AST/GenericEnvironment.h" +#include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" #include "swift/AST/ParameterList.h" @@ -1365,12 +1367,14 @@ namespace { // Handle generic types. GenericParamList *genericParams = nullptr; GenericSignature *genericSig = nullptr; + GenericEnvironment *genericEnv = nullptr; auto underlyingType = typeDecl->getDeclaredInterfaceType(); if (auto generic = dyn_cast(typeDecl)) { if (generic->getGenericSignature() && !isa(typeDecl)) { genericParams = generic->getGenericParams(); genericSig = generic->getGenericSignature(); + genericEnv = generic->getGenericEnvironment(); underlyingType = ArchetypeBuilder::mapTypeIntoContext( generic, underlyingType); @@ -1395,6 +1399,7 @@ namespace { genericParams, dc); alias->computeType(); alias->setGenericSignature(genericSig); + alias->setGenericEnvironment(genericEnv); // Record that this is the Swift 2 version of this declaration. Impl.ImportedDecls[{decl->getCanonicalDecl(), true}] = alias; @@ -3133,6 +3138,7 @@ namespace { result->setType(fnType); result->setInterfaceType(interfaceType); result->setGenericSignature(dc->getGenericSignatureOfContext()); + result->setGenericEnvironment(dc->getGenericEnvironmentOfContext()); result->setBodyResultType(swiftResultTy); result->setAccessibility(Accessibility::Public); @@ -3912,6 +3918,7 @@ namespace { result->setType(type); result->setInterfaceType(interfaceType); result->setGenericSignature(dc->getGenericSignatureOfContext()); + result->setGenericEnvironment(dc->getGenericEnvironmentOfContext()); // Optional methods in protocols. if (decl->getImplementationControl() == clang::ObjCMethodDecl::Optional && @@ -4386,6 +4393,7 @@ namespace { result->setInitializerInterfaceType(interfaceInitType); result->setInterfaceType(interfaceAllocType); result->setGenericSignature(dc->getGenericSignatureOfContext()); + result->setGenericEnvironment(dc->getGenericEnvironmentOfContext()); result->setType(allocType); @@ -4523,6 +4531,8 @@ namespace { thunk->setBodyResultType(elementTy); thunk->setInterfaceType(interfaceType); thunk->setGenericSignature(dc->getGenericSignatureOfContext()); + thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext()); + thunk->setAccessibility(getOverridableAccessibility(dc)); auto objcAttr = getter->getAttrs().getAttribute(); @@ -4594,6 +4604,8 @@ namespace { thunk->setBodyResultType(TupleType::getEmpty(C)); thunk->setInterfaceType(interfaceType); thunk->setGenericSignature(dc->getGenericSignatureOfContext()); + thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext()); + thunk->setAccessibility(getOverridableAccessibility(dc)); auto objcAttr = setter->getAttrs().getAttribute(); @@ -5143,22 +5155,24 @@ namespace { Impl.importSourceLoc(typeParamList->getRAngleLoc())); } - // Calculate the generic signature for the given imported generic param - // list. If there are any errors in doing so, return 'nullptr'. - GenericSignature *calculateGenericSignature(GenericParamList *genericParams, - DeclContext *dc) { + // Calculate the generic signature and interface type to archetype mapping + // from an imported generic param list. + std::pair + calculateGenericSignature(GenericParamList *genericParams, + DeclContext *dc) { ArchetypeBuilder builder(*dc->getParentModule(), Impl.SwiftContext.Diags); for (auto param : *genericParams) builder.addGenericParameter(param); for (auto param : *genericParams) { - if (builder.addGenericParameterRequirements(param)) { - return nullptr; - } + bool result = builder.addGenericParameterRequirements(param); + assert(!result); + (void) result; } // TODO: any need to infer requirements? - if (builder.finalize(genericParams->getSourceRange().Start)) { - return nullptr; - } + bool result = builder.finalize(genericParams->getSourceRange().Start); + assert(!result); + (void) result; + SmallVector genericParamTypes; for (auto param : *genericParams) { genericParamTypes.push_back( @@ -5166,10 +5180,11 @@ namespace { auto *archetype = builder.getArchetype(param); param->setArchetype(archetype); } - genericParams->setAllArchetypes( - Impl.SwiftContext.AllocateCopy(builder.getAllArchetypes())); - return builder.getGenericSignature(genericParamTypes); + auto *sig = builder.getGenericSignature(genericParamTypes); + auto *env = builder.getGenericEnvironment(genericParamTypes); + + return std::make_pair(sig, env); } /// Import members of the given Objective-C container and add them to the @@ -5507,11 +5522,14 @@ namespace { auto genericParams = GenericParamList::create(Impl.SwiftContext, SourceLoc(), toGenericParams, SourceLoc()); result->setGenericParams(genericParams); - if (auto sig = calculateGenericSignature(genericParams, result)) { - result->setGenericSignature(sig); - } else { - return nullptr; - } + + GenericSignature *sig; + GenericEnvironment *env; + std::tie(sig, env) = calculateGenericSignature(genericParams, result); + + result->setGenericSignature(sig); + result->setGenericEnvironment(env); + // Calculate the correct bound-generic extended type. SmallVector genericArgs; for (auto gp : *genericParams) { @@ -5669,12 +5687,6 @@ namespace { Type(result->getDeclaredType()), Type(), false); selfDecl->setArchetype(selfArchetype); - - // Set AllArchetypes of the protocol. ObjC protocols don't have associated - // types so only the Self archetype is present. - - result->getGenericParams()->setAllArchetypes( - Impl.SwiftContext.AllocateCopy(llvm::makeArrayRef(selfArchetype))); // Set the generic parameters and requirements. auto genericParam = selfDecl->getDeclaredType() @@ -5687,6 +5699,15 @@ namespace { auto sig = GenericSignature::get(genericParam, genericRequirements); result->setGenericSignature(sig); + TypeSubstitutionMap interfaceToArchetypeMap; + + auto paramTy = selfDecl->getDeclaredType()->getCanonicalType(); + interfaceToArchetypeMap[paramTy.getPointer()] = selfArchetype; + + auto *env = + GenericEnvironment::get(Impl.SwiftContext, interfaceToArchetypeMap); + result->setGenericEnvironment(env); + result->setCircularityCheck(CircularityCheck::Checked); // Import protocols this protocol conforms to. @@ -5818,11 +5839,13 @@ namespace { auto genericParams = *gpImportResult; if (genericParams) { result->setGenericParams(genericParams); - if (auto sig = calculateGenericSignature(genericParams, result)) { - result->setGenericSignature(sig); - } else { - return nullptr; - } + + GenericSignature *sig; + GenericEnvironment *env; + std::tie(sig, env) = calculateGenericSignature(genericParams, result); + + result->setGenericSignature(sig); + result->setGenericEnvironment(env); } } else { return nullptr; @@ -6967,8 +6990,6 @@ ClangImporter::Implementation::importDeclContextOf( conformsTo, protoArchetype->getSuperclass(), protoArchetype->getIsRecursive()); extSelf->setArchetype(extSelfArchetype); - ext->getGenericParams()->setAllArchetypes( - SwiftContext.AllocateCopy(llvm::makeArrayRef(extSelfArchetype))); auto genericParam = extSelf->getDeclaredType()->castTo(); @@ -6976,8 +6997,17 @@ ClangImporter::Implementation::importDeclContextOf( Requirement(RequirementKind::WitnessMarker, genericParam, Type()), Requirement(RequirementKind::Conformance, genericParam, protoDecl->getDeclaredType())}; - auto sig = GenericSignature::get(genericParam, genericRequirements); + auto *sig = GenericSignature::get(genericParam, genericRequirements); ext->setGenericSignature(sig); + + TypeSubstitutionMap interfaceToArchetypeMap; + + auto paramTy = extSelf->getDeclaredType()->getCanonicalType(); + interfaceToArchetypeMap[paramTy.getPointer()] = extSelfArchetype; + + auto *env = + GenericEnvironment::get(SwiftContext, interfaceToArchetypeMap); + ext->setGenericEnvironment(env); } // Add the extension to the nominal type. diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 3333be2d0b576..8d9a5db657fde 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -236,7 +236,7 @@ static void emitPolymorphicParametersFromArray(IRGenFunction &IGF, array = IGF.Builder.CreateElementBitCast(array, IGF.IGM.TypeMetadataPtrTy); auto getInContext = [&](CanType type) -> CanType { - return ArchetypeBuilder::mapTypeIntoContext(typeDecl, type, nullptr) + return ArchetypeBuilder::mapTypeIntoContext(typeDecl, type) ->getCanonicalType(); }; @@ -2767,7 +2767,7 @@ irgen::emitFieldTypeAccessor(IRGenModule &IGM, auto declCtxt = type; if (auto generics = declCtxt->getGenericSignatureOfContext()) { auto getInContext = [&](CanType type) -> CanType { - return ArchetypeBuilder::mapTypeIntoContext(declCtxt, type, nullptr) + return ArchetypeBuilder::mapTypeIntoContext(declCtxt, type) ->getCanonicalType(); }; bindArchetypeAccessPaths(IGF, generics, getInContext); diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index 5da8cb190e828..1c93bf600b709 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -1281,7 +1281,7 @@ class AccessorConformanceInfo : public ConformanceInfo { auto declCtx = Conformance.getDeclContext(); if (auto generics = declCtx->getGenericSignatureOfContext()) { auto getInContext = [&](CanType type) -> CanType { - return ArchetypeBuilder::mapTypeIntoContext(declCtx, type, nullptr) + return ArchetypeBuilder::mapTypeIntoContext(declCtx, type) ->getCanonicalType(); }; bindArchetypeAccessPaths(IGF, generics, getInContext); diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp index fa2bee07ce9ae..c8dc4a633fad6 100644 --- a/lib/Parse/ParseSIL.cpp +++ b/lib/Parse/ParseSIL.cpp @@ -13,6 +13,7 @@ #include "swift/Basic/Defer.h" #include "swift/Basic/Fallthrough.h" #include "swift/AST/ArchetypeBuilder.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/NameLookup.h" #include "swift/Parse/Parser.h" #include "swift/Parse/Lexer.h" @@ -213,12 +214,14 @@ namespace { bool parseASTType(CanType &result); bool parseSILType(SILType &Result, GenericSignature *&genericSig, + GenericEnvironment *&genericEnv, GenericParamList *&genericParams, bool IsFuncDecl = false); bool parseSILType(SILType &Result) { GenericSignature *IgnoredSig; + GenericEnvironment *IgnoredEnv; GenericParamList *IgnoredParams; - return parseSILType(Result, IgnoredSig, IgnoredParams); + return parseSILType(Result, IgnoredSig, IgnoredEnv, IgnoredParams); } bool parseSILType(SILType &Result, SourceLoc &TypeLoc) { TypeLoc = P.Tok.getLoc(); @@ -226,9 +229,10 @@ namespace { } bool parseSILType(SILType &Result, SourceLoc &TypeLoc, GenericSignature *&GenericSig, + GenericEnvironment *&GenericEnv, GenericParamList *&GenericParams) { TypeLoc = P.Tok.getLoc(); - return parseSILType(Result, GenericSig, GenericParams); + return parseSILType(Result, GenericSig, GenericEnv, GenericParams); } /// Parse a SIL type without the leading '$' or value category specifier. @@ -236,15 +240,18 @@ namespace { SILValueCategory category, const TypeAttributes &attrs, GenericSignature *&genericSig, + GenericEnvironment *&genericEnv, GenericParamList *&genericParams, bool IsFuncDecl = false); bool parseSILTypeWithoutQualifiers(SILType &Result, SILValueCategory category, const TypeAttributes &attrs) { GenericSignature *IgnoredSig; + GenericEnvironment *IgnoredEnv; GenericParamList *IgnoredParams; return parseSILTypeWithoutQualifiers(Result, category, attrs, - IgnoredSig, IgnoredParams); + IgnoredSig, IgnoredEnv, + IgnoredParams); } bool parseSILDottedPath(ValueDecl *&Decl, @@ -305,13 +312,15 @@ namespace { ProtocolConformance *parseProtocolConformance(ProtocolDecl *&proto, GenericSignature *&genericSig, + GenericEnvironment *&genericEnv, GenericParamList *&genericParams, bool localScope); ProtocolConformance *parseProtocolConformance() { ProtocolDecl *dummy; GenericSignature *sig; + GenericEnvironment *env; GenericParamList *gp; - return parseProtocolConformance(dummy, sig, gp, true); + return parseProtocolConformance(dummy, sig, env, gp, true); } Optional @@ -838,9 +847,11 @@ bool SILParser::parseSILTypeWithoutQualifiers(SILType &Result, SILValueCategory category, const TypeAttributes &attrs, GenericSignature *&GenericSig, + GenericEnvironment *&GenericEnv, GenericParamList *&GenericParams, bool IsFuncDecl){ GenericSig = nullptr; + GenericEnv = nullptr; GenericParams = nullptr; // If this is part of a function decl, generic parameters are visible in the @@ -862,8 +873,10 @@ bool SILParser::parseSILTypeWithoutQualifiers(SILType &Result, if (auto generics = fnType->getGenericParams()) { GenericParams = generics; - GenericSig = handleSILGenericParams(P.Context, generics, &P.SF); + std::tie(GenericSig, GenericEnv) = + handleSILGenericParams(P.Context, generics, &P.SF); fnType->setGenericSignature(GenericSig); + fnType->setGenericEnvironment(GenericEnv); } } @@ -888,9 +901,11 @@ bool SILParser::parseSILTypeWithoutQualifiers(SILType &Result, /// bool SILParser::parseSILType(SILType &Result, GenericSignature *&GenericSig, + GenericEnvironment *&GenericEnv, GenericParamList *&GenericParams, bool IsFuncDecl){ GenericSig = nullptr; + GenericEnv = nullptr; GenericParams = nullptr; if (P.parseToken(tok::sil_dollar, diag::expected_sil_type)) @@ -914,7 +929,7 @@ bool SILParser::parseSILType(SILType &Result, attrs.convention = "thin"; } return parseSILTypeWithoutQualifiers(Result, category, attrs, - GenericSig, GenericParams, + GenericSig, GenericEnv, GenericParams, IsFuncDecl); } @@ -1479,20 +1494,22 @@ static bool getConformancesForSubstitution(Parser &P, /// from a SILFunctionType. bool getApplySubstitutionsFromParsed( SILParser &SP, - GenericSignature *sig, GenericParamList *params, + GenericSignature *sig, + GenericEnvironment *env, ArrayRef parses, SmallVectorImpl &subs) { if (parses.empty()) { - assert (!sig && !params); + assert (!sig && !env); return false; } - assert(sig && params); + assert(sig && env); + + auto loc = params->getRAngleLoc(); // Map from interface types to archetypes - TypeSubstitutionMap map; - params->getForwardingSubstitutionMap(map); + TypeSubstitutionMap map = env->getInterfaceToArchetypeMap(); auto *mod = SP.SILMod.getSwiftModule(); @@ -1504,7 +1521,7 @@ bool getApplySubstitutionsFromParsed( auto *archetype = contextTy->castTo(); if (parses.empty()) { - SP.P.diagnose(params->getRAngleLoc(), diag::sil_missing_substitutions); + SP.P.diagnose(loc, diag::sil_missing_substitutions); return true; } auto parsed = parses.front(); @@ -1520,7 +1537,7 @@ bool getApplySubstitutionsFromParsed( SP.P.Context.AllocateCopy(conformances)}); } if (!parses.empty()) { - SP.P.diagnose(params->getRAngleLoc(), diag::sil_too_many_substitutions); + SP.P.diagnose(loc, diag::sil_too_many_substitutions); return true; } return false; @@ -1882,6 +1899,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { auto *builtinFunc = cast(foundBuiltins[0]); GenericSignature *genericSig = builtinFunc->getGenericSignature(); + GenericEnvironment *genericEnv = builtinFunc->getGenericEnvironment(); GenericParamList *genericParams = builtinFunc->getGenericParams(); SmallVector parsedSubs; @@ -1894,7 +1912,10 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { P.diagnose(P.Tok, diag::sil_substitutions_on_non_polymorphic_type); return true; } - if (getApplySubstitutionsFromParsed(*this, genericSig, genericParams, + if (getApplySubstitutionsFromParsed(*this, + genericParams, + genericSig, + genericEnv, parsedSubs, subs)) return true; } @@ -2381,6 +2402,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { ParsedSetterSubs; GenericSignature *InitStorageSig, *SetterSig; GenericParamList *InitStorageParams, *SetterParams; + GenericEnvironment *InitStorageEnv, *SetterEnv; SILType InitStorageTy, SetterTy; // mark_uninitialized_behavior %init(%storage) : $T -> U, @@ -2391,7 +2413,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { || parseValueName(StorageName) || P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") - || parseSILType(InitStorageTy, InitStorageSig, InitStorageParams) + || parseSILType(InitStorageTy, InitStorageSig, InitStorageEnv, InitStorageParams) || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") || parseValueName(SetterFuncName) || parseApplySubstitutions(ParsedSetterSubs) @@ -2399,7 +2421,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { || parseValueName(SelfName) || P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") - || parseSILType(SetterTy, SetterSig, SetterParams)) + || parseSILType(SetterTy, SetterSig, SetterEnv, SetterParams)) return true; // Resolve the types of the operands. @@ -2409,9 +2431,12 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { SmallVector InitStorageSubs, SetterSubs; if (getApplySubstitutionsFromParsed(*this, - InitStorageSig, InitStorageParams, + InitStorageParams, + InitStorageSig, InitStorageEnv, ParsedInitStorageSubs, InitStorageSubs) - || getApplySubstitutionsFromParsed(*this, SetterSig, SetterParams, + || getApplySubstitutionsFromParsed(*this, + SetterParams, + SetterSig, SetterEnv, ParsedSetterSubs, SetterSubs)) return true; @@ -2913,8 +2938,12 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { if (auto generics = fnType->getGenericParams()) { assert(!Ty.wasValidated() && Ty.getType().isNull()); - auto *genericSig = handleSILGenericParams(P.Context, generics, &P.SF); + GenericSignature *genericSig; + GenericEnvironment *genericEnv; + std::tie(genericSig, genericEnv) = + handleSILGenericParams(P.Context, generics, &P.SF); fnType->setGenericSignature(genericSig); + fnType->setGenericEnvironment(genericEnv); } } @@ -3615,6 +3644,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { UnresolvedValueName invokeName; SILType invokeTy; GenericSignature *invokeGenericSig; + GenericEnvironment *invokeGenericEnv; GenericParamList *invokeGenericParams; SILType blockType; @@ -3628,7 +3658,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { parseValueName(invokeName) || parseApplySubstitutions(parsedSubs) || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") || - parseSILType(invokeTy, invokeGenericSig, invokeGenericParams) || + parseSILType(invokeTy, invokeGenericSig, invokeGenericEnv, invokeGenericParams) || P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") || parseSILIdentifier(type, typeLoc, diag::expected_tok_in_sil_instr, "type") || @@ -3654,8 +3684,9 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { return true; } if (getApplySubstitutionsFromParsed(*this, - invokeGenericSig, invokeGenericParams, + invokeGenericSig, + invokeGenericEnv, parsedSubs, subs)) return true; } @@ -3702,10 +3733,11 @@ bool SILParser::parseCallInstruction(SILLocation InstLoc, SILType Ty; SourceLoc TypeLoc; GenericSignature *GenericSig = nullptr; + GenericEnvironment *GenericEnv = nullptr; GenericParamList *GenericParams = nullptr; if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")") || P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":") || - parseSILType(Ty, TypeLoc, GenericSig, GenericParams)) + parseSILType(Ty, TypeLoc, GenericSig, GenericEnv, GenericParams)) return true; auto FTI = Ty.getAs(); @@ -3716,11 +3748,13 @@ bool SILParser::parseCallInstruction(SILLocation InstLoc, SmallVector subs; if (!parsedSubs.empty()) { - if (!GenericParams) { + if (!GenericSig) { P.diagnose(TypeLoc, diag::sil_substitutions_on_non_polymorphic_type); return true; } - if (getApplySubstitutionsFromParsed(*this, GenericSig, GenericParams, + if (getApplySubstitutionsFromParsed(*this, + GenericParams, + GenericSig, GenericEnv, parsedSubs, subs)) return true; } @@ -3958,8 +3992,10 @@ bool Parser::parseDeclSIL() { // the scope. Scope Body(this, ScopeKind::FunctionBody); GenericSignature *GenericSig; - GenericParamList *ContextParams; - if (FunctionState.parseSILType(FnType, GenericSig, ContextParams, + GenericEnvironment *GenericEnv; + GenericParamList *GenericParams; + if (FunctionState.parseSILType(FnType, + GenericSig, GenericEnv, GenericParams, true/*IsFuncDecl*/)) return true; auto SILFnType = FnType.getAs(); @@ -3989,17 +4025,15 @@ bool Parser::parseDeclSIL() { if (consumeIf(tok::l_brace)) { isDefinition = true; - // FIXME: Get the generic parameters from the function type. We'll want - // to parse this from the TypeRepr when SILFunctionType loses its context - // params. - FunctionState.F->setContextGenericParams(ContextParams); + FunctionState.F->setGenericEnvironment(GenericEnv); - // Resolve specialization attributes after setting ContextParams. + // Resolve specialization attributes after setting GenericEnv. for (auto &Attr : SpecAttrs) { SmallVector Subs; if (getApplySubstitutionsFromParsed(FunctionState, + GenericParams, GenericSig, - ContextParams, + GenericEnv, Attr.subs, Subs)) { return true; } @@ -4341,6 +4375,7 @@ bool SILParser::parseSpecConformanceSubstitutions( ProtocolConformance *SILParser::parseProtocolConformance( ProtocolDecl *&proto, GenericSignature *&genericSig, + GenericEnvironment *&genericEnv, GenericParamList *&genericParams, bool localScope) { // Parse generic params for the protocol conformance. We need to make sure @@ -4354,7 +4389,8 @@ ProtocolConformance *SILParser::parseProtocolConformance( genericParams = P.maybeParseGenericParams().getPtrOrNull(); if (genericParams) { - genericSig = handleSILGenericParams(P.Context, genericParams, &P.SF); + std::tie(genericSig, genericEnv) = + handleSILGenericParams(P.Context, genericParams, &P.SF); } ProtocolConformance *retVal = parseProtocolConformanceHelper(proto, @@ -4402,15 +4438,19 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper( return nullptr; ProtocolDecl *dummy; GenericSignature *sig; + GenericEnvironment *env; GenericParamList *gp; - auto genericConform = parseProtocolConformance(dummy, sig, gp, localScope); + auto genericConform = parseProtocolConformance(dummy, sig, env, gp, + localScope); if (!genericConform) return nullptr; if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen)) return nullptr; SmallVector subs; - if (getApplySubstitutionsFromParsed(*this, sig, gp, parsedSubs, subs)) + if (getApplySubstitutionsFromParsed(*this, + gp, + sig, env, parsedSubs, subs)) return nullptr; auto result = P.Context.getSpecializedConformance( @@ -4471,9 +4511,12 @@ bool Parser::parseSILWitnessTable() { // Parse the protocol conformance. ProtocolDecl *proto; GenericSignature *dummySig; + GenericEnvironment *dummyEnv; GenericParamList *dummyParams; auto conf = WitnessState.parseProtocolConformance(proto, - dummySig, dummyParams, + dummySig, + dummyEnv, + dummyParams, false/*localScope*/); NormalProtocolConformance *theConformance = conf ? @@ -4906,12 +4949,13 @@ bool Parser::parseSILScope() { // We need to turn on InSILBody to parse the function reference. Lexer::SILBodyRAII Tmp(*L); GenericSignature *IgnoredSig; + GenericEnvironment *IgnoredEnv; GenericParamList *IgnoredParams; Scope S(this, ScopeKind::TopLevel); Scope Body(this, ScopeKind::FunctionBody); if ((ScopeState.parseGlobalName(FnName)) || parseToken(tok::colon, diag::expected_sil_colon_value_ref) || - ScopeState.parseSILType(Ty, IgnoredSig, IgnoredParams, true)) + ScopeState.parseSILType(Ty, IgnoredSig, IgnoredEnv, IgnoredParams, true)) return true; // The function doesn't exist yet. Create a zombie forward declaration. diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp index 533b4707fe2c0..9637a63445598 100644 --- a/lib/SIL/SILFunction.cpp +++ b/lib/SIL/SILFunction.cpp @@ -16,8 +16,8 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/CFG.h" -// FIXME: For mapTypeInContext #include "swift/AST/ArchetypeBuilder.h" +#include "swift/AST/GenericEnvironment.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/GraphWriter.h" @@ -41,7 +41,7 @@ SILSpecializeAttr *SILSpecializeAttr::create(SILModule &M, SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage, StringRef name, CanSILFunctionType loweredType, - GenericParamList *contextGenericParams, + GenericEnvironment *genericEnv, Optional loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, @@ -62,7 +62,7 @@ SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage, } auto fn = new (M) SILFunction(M, linkage, name, - loweredType, contextGenericParams, loc, + loweredType, genericEnv, loc, isBareSILFunction, isTrans, isFragile, isThunk, classVisibility, inlineStrategy, E, insertBefore, debugScope, DC); @@ -73,7 +73,7 @@ SILFunction *SILFunction::create(SILModule &M, SILLinkage linkage, SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name, CanSILFunctionType LoweredType, - GenericParamList *contextGenericParams, + GenericEnvironment *genericEnv, Optional Loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, @@ -87,8 +87,7 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, : Module(Module), Name(Name), LoweredType(LoweredType), - // FIXME: Context params should be independent of the function type. - ContextGenericParams(contextGenericParams), + GenericEnv(genericEnv), DeclCtx(DC), DebugScope(DebugScope), Bare(isBareSILFunction), @@ -188,7 +187,7 @@ bool SILFunction::shouldOptimize() const { Type SILFunction::mapTypeIntoContext(Type type) const { return ArchetypeBuilder::mapTypeIntoContext(getModule().getSwiftModule(), - getContextGenericParams(), + getGenericEnvironment(), type); } @@ -290,7 +289,7 @@ SILType ArchetypeBuilder::substDependentType(SILModule &M, SILType type) { Type SILFunction::mapTypeOutOfContext(Type type) const { return ArchetypeBuilder::mapTypeOutOfContext(getModule().getSwiftModule(), - getContextGenericParams(), + getGenericEnvironment(), type); } @@ -558,12 +557,13 @@ ArrayRef SILFunction::getForwardingSubstitutions() { if (ForwardingSubs) return *ForwardingSubs; - auto *params = getContextGenericParams(); - if (!params) + auto *env = getGenericEnvironment(); + if (!env) return {}; auto sig = getLoweredFunctionType()->getGenericSignature(); - ForwardingSubs = params->getForwardingSubstitutions(sig); + auto *M = getModule().getSwiftModule(); + ForwardingSubs = env->getForwardingSubstitutions(M, sig); return *ForwardingSubs; } diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index 7754fd64e3984..da2c1ccb825a1 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -1682,9 +1682,7 @@ SILConstantInfo TypeConverter::getConstantInfo(SILDeclRef constant) { // First, get a function type for the constant. This creates the // right type for a getter or setter. auto formalInterfaceType = makeConstantInterfaceType(constant); - GenericParamList *contextGenerics, *innerGenerics; - std::tie(contextGenerics, innerGenerics) - = getConstantContextGenericParams(constant); + auto *genericEnv = getConstantGenericEnvironment(constant); // The formal type is just that with the right representation. auto rep = getDeclRefRepresentation(constant); @@ -1714,8 +1712,7 @@ SILConstantInfo TypeConverter::getConstantInfo(SILDeclRef constant) { formalInterfaceType, loweredInterfaceType, silFnType, - contextGenerics, - innerGenerics, + genericEnv }; ConstantTypes[constant] = result; return result; @@ -2091,8 +2088,7 @@ SILConstantInfo TypeConverter::getConstantOverrideInfo(SILDeclRef derived, SILConstantInfo overrideInfo; overrideInfo.LoweredInterfaceType = overrideLoweredInterfaceTy; overrideInfo.SILFnType = fnTy; - overrideInfo.ContextGenericParams = derivedInfo.ContextGenericParams; - overrideInfo.InnerGenericParams = derivedInfo.InnerGenericParams; + overrideInfo.GenericEnv = derivedInfo.GenericEnv; ConstantOverrideTypes[{derived, base}] = overrideInfo; return overrideInfo; diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp index 8c2ef8dbcdc87..dc73acbd1b275 100644 --- a/lib/SIL/SILModule.cpp +++ b/lib/SIL/SILModule.cpp @@ -409,13 +409,13 @@ SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc, SILFunction *SILModule::createFunction( SILLinkage linkage, StringRef name, CanSILFunctionType loweredType, - GenericParamList *contextGenericParams, Optional loc, + GenericEnvironment *genericEnv, Optional loc, IsBare_t isBareSILFunction, IsTransparent_t isTrans, IsFragile_t isFragile, IsThunk_t isThunk, SILFunction::ClassVisibility_t classVisibility, Inline_t inlineStrategy, EffectsKind EK, SILFunction *InsertBefore, const SILDebugScope *DebugScope, DeclContext *DC) { return SILFunction::create(*this, linkage, name, loweredType, - contextGenericParams, loc, isBareSILFunction, + genericEnv, loc, isBareSILFunction, isTrans, isFragile, isThunk, classVisibility, inlineStrategy, EK, InsertBefore, DebugScope, DC); } diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index ad3bb3eb4f38d..4baac97cef75c 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -1794,33 +1794,35 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { llvm::DenseMap Aliases; llvm::DenseSet UsedNames; - auto params = ContextGenericParams; - llvm::SmallString<16> disambiguatedNameBuf; - unsigned disambiguatedNameCounter = 1; - while (params) { - for (GenericTypeParamDecl *param : params->getParams()) { - Identifier name = param->getName(); + auto sig = getLoweredFunctionType()->getGenericSignature(); + auto *env = getGenericEnvironment(); + if (sig && env) { + llvm::SmallString<16> disambiguatedNameBuf; + unsigned disambiguatedNameCounter = 1; + for (auto *paramTy : sig->getGenericParams()) { + auto *archetypeTy = mapTypeIntoContext(paramTy)->getAs(); + assert(archetypeTy); + + Identifier name = archetypeTy->getName(); while (!UsedNames.insert(name).second) { disambiguatedNameBuf.clear(); { llvm::raw_svector_ostream names(disambiguatedNameBuf); - names << param->getName() << disambiguatedNameCounter++; + names << archetypeTy->getName() << disambiguatedNameCounter++; } name = getASTContext().getIdentifier(disambiguatedNameBuf); } - if (name != param->getName()) - Aliases[CanType(param->getArchetype())] = name; + if (name != archetypeTy->getName()) + Aliases[CanType(archetypeTy)] = name; } - - params = params->getOuterParameters(); } { - PrintOptions withContextGenericParams = PrintOptions::printSIL(); - withContextGenericParams.ContextGenericParams = ContextGenericParams; - withContextGenericParams.AlternativeTypeNames = + PrintOptions withGenericEnvironment = PrintOptions::printSIL(); + withGenericEnvironment.GenericEnv = env; + withGenericEnvironment.AlternativeTypeNames = Aliases.empty() ? nullptr : &Aliases; - LoweredType->print(OS, withContextGenericParams); + LoweredType->print(OS, withGenericEnvironment); } if (!isExternalDeclaration()) { diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp index 9b9e89215af55..beb3fa42bc12a 100644 --- a/lib/SIL/SILVerifier.cpp +++ b/lib/SIL/SILVerifier.cpp @@ -22,6 +22,7 @@ #include "swift/AST/AnyFunctionRef.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Decl.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Module.h" #include "swift/AST/Types.h" #include "swift/SIL/PrettyStackTrace.h" @@ -59,15 +60,10 @@ static bool isArchetypeValidInFunction(ArchetypeType *A, SILFunction *F) { A = A->getPrimary(); // Ok, we have a primary archetype, make sure it is in the nested generic - // parameters of our caller. - for (auto *params = F->getContextGenericParams(); - params != nullptr; - params = params->getOuterParameters()) { - - for (auto param : params->getParams()) - if (param->getArchetype()->isEqual(A)) - return true; - } + // environment of our caller. + if (auto *genericEnv = F->getGenericEnvironment()) + if (genericEnv->getArchetypeToInterfaceMap().count(A)) + return true; return false; } @@ -1757,9 +1753,9 @@ class SILVerifier : public SILVerifierBase { auto methodTy = constantInfo.SILFnType; // Map interface types to archetypes. - if (auto *params = constantInfo.ContextGenericParams) { + if (auto *env = constantInfo.GenericEnv) { auto sig = constantInfo.SILFnType->getGenericSignature(); - auto subs = params->getForwardingSubstitutions(sig); + auto subs = env->getForwardingSubstitutions(M, sig); methodTy = methodTy->substGenericArgs(F.getModule(), M, subs); } assert(!methodTy->isPolymorphic()); @@ -3308,13 +3304,13 @@ class SILVerifier : public SILVerifierBase { // Make sure that our SILFunction only has context generic params if our // SILFunctionType is non-polymorphic. - if (F->getContextGenericParams()) { + if (F->getGenericEnvironment()) { require(FTy->isPolymorphic(), - "non-generic function definitions cannot have context " - "archetypes"); + "non-generic function definitions cannot have a " + "generic environment"); } else { require(!FTy->isPolymorphic(), - "generic function definition must have context archetypes"); + "generic function definition must have a generic environment"); } // Otherwise, verify the body of the function. diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index e4d4c6cbc9c20..14aca5fa79e0e 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -1658,7 +1658,7 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType( sig = genTy->getGenericSignature()->getCanonicalSignature(); resultTy = ArchetypeBuilder::mapTypeOutOfContext( TC.M.getSwiftModule(), - funcInfo.ContextGenericParams, + funcInfo.GenericEnv, resultTy)->getCanonicalType(); } @@ -1748,16 +1748,16 @@ static CanAnyFunctionType getIVarInitDestroyerInterfaceType(ClassDecl *cd, return CanFunctionType::get(classType, resultType, extInfo); } -GenericParamList * -TypeConverter::getEffectiveGenericParams(AnyFunctionRef fn, - CaptureInfo captureInfo) { +GenericEnvironment * +TypeConverter::getEffectiveGenericEnvironment(AnyFunctionRef fn, + CaptureInfo captureInfo) { auto dc = fn.getAsDeclContext(); if (dc->getParent()->isLocalContext() && !captureInfo.hasGenericParamCaptures()) return nullptr; - return dc->getGenericParamsOfContext(); + return dc->getGenericEnvironmentOfContext(); } CanGenericSignature @@ -1904,9 +1904,9 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) { } } -/// Get the context generic parameters for an entity. -std::pair -TypeConverter::getConstantContextGenericParams(SILDeclRef c) { +/// Get the generic environment for an entity. +GenericEnvironment * +TypeConverter::getConstantGenericEnvironment(SILDeclRef c) { ValueDecl *vd = c.loc.dyn_cast(); /// Get the function generic params, including outer params. @@ -1915,48 +1915,37 @@ TypeConverter::getConstantContextGenericParams(SILDeclRef c) { if (auto *ACE = c.getAbstractClosureExpr()) { auto captureInfo = getLoweredLocalCaptures(ACE); - // Closures are currently never natively generic. - return {getEffectiveGenericParams(ACE, captureInfo), nullptr}; + return getEffectiveGenericEnvironment(ACE, captureInfo); } FuncDecl *func = cast(vd); auto captureInfo = getLoweredLocalCaptures(func); - return {getEffectiveGenericParams(func, captureInfo), - func->getGenericParams()}; + return getEffectiveGenericEnvironment(func, captureInfo); } case SILDeclRef::Kind::EnumElement: { auto eltDecl = cast(vd); - return { - eltDecl->getDeclContext()->getGenericParamsOfContext(), - nullptr - }; + return eltDecl->getDeclContext()->getGenericEnvironmentOfContext(); } case SILDeclRef::Kind::Allocator: case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::Destroyer: case SILDeclRef::Kind::Deallocator: { auto *afd = cast(vd); - return {afd->getGenericParamsOfContext(), afd->getGenericParams()}; + return afd->getGenericEnvironmentOfContext(); } case SILDeclRef::Kind::GlobalAccessor: case SILDeclRef::Kind::GlobalGetter: { - return { - cast(vd)->getDeclContext()->getGenericParamsOfContext(), - nullptr, - }; + return vd->getDeclContext()->getGenericEnvironmentOfContext(); } case SILDeclRef::Kind::IVarInitializer: case SILDeclRef::Kind::IVarDestroyer: - return {cast(vd)->getGenericParamsOfContext(), nullptr}; + return cast(vd)->getGenericEnvironmentOfContext(); case SILDeclRef::Kind::DefaultArgGenerator: - // Use the context generic parameters of the original declaration. - return getConstantContextGenericParams(SILDeclRef(c.getDecl())); + // Use the generic environment of the original function. + return getConstantGenericEnvironment(SILDeclRef(c.getDecl())); case SILDeclRef::Kind::StoredPropertyInitializer: - // Use the context generic parameters of the containing type. - return { - c.getDecl()->getDeclContext()->getGenericParamsOfContext(), - nullptr, - }; + // Use the generic environment of the containing type. + return c.getDecl()->getDeclContext()->getGenericEnvironmentOfContext(); } } diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 43d637fed1b7a..e8682ecdca746 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -575,8 +575,7 @@ void SILGenModule::preEmitFunction(SILDeclRef constant, assert(F->empty() && "already emitted function?!"); - F->setContextGenericParams( - Types.getConstantInfo(constant).ContextGenericParams); + F->setGenericEnvironment(Types.getConstantInfo(constant).GenericEnv); // Create a debug scope for the function using astNode as source location. F->setDebugScope(new (M) SILDebugScope(Loc, F)); diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h index e019161baa89b..ba393c71ba239 100644 --- a/lib/SILGen/SILGen.h +++ b/lib/SILGen/SILGen.h @@ -185,7 +185,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { /// Get or create the declaration of a reabstraction thunk with the /// given signature. SILFunction *getOrCreateReabstractionThunk( - GenericParamList *thunkContextParams, + GenericEnvironment *genericEnv, CanSILFunctionType thunkType, CanSILFunctionType fromType, CanSILFunctionType toType, diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index ce9c2bf1c0c87..5e247c384f1d9 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -321,14 +321,10 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, // Build the invoke function signature. The block will capture the original // function value. auto fnTy = fn.getType().castTo(); - auto fnInterfaceTy = cast(CanType( - ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(), - F.getContextGenericParams(), - fnTy))); - auto blockInterfaceTy = cast(CanType( - ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(), - F.getContextGenericParams(), - blockTy))); + auto fnInterfaceTy = cast( + F.mapTypeOutOfContext(fnTy)->getCanonicalType()); + auto blockInterfaceTy = cast( + F.mapTypeOutOfContext(blockTy)->getCanonicalType()); auto storageTy = SILBlockStorageType::get(fnTy); auto storageInterfaceTy = SILBlockStorageType::get(fnInterfaceTy); @@ -363,7 +359,7 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, // Create the invoke function. Borrow the mangling scheme from reabstraction // thunks, which is what we are in spirit. - auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(), + auto thunk = SGM.getOrCreateReabstractionThunk(F.getGenericEnvironment(), invokeTy, fnTy, blockTy, @@ -371,7 +367,7 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, // Build it if necessary. if (thunk->empty()) { - thunk->setContextGenericParams(F.getContextGenericParams()); + thunk->setGenericEnvironment(F.getGenericEnvironment()); SILGenFunction thunkSGF(SGM, *thunk); auto loc = RegularLocation::getAutoGeneratedLocation(); buildFuncToBlockInvokeBody(thunkSGF, loc, blockTy, storageTy, fnTy); @@ -612,7 +608,7 @@ SILGenFunction::emitBlockToFunc(SILLocation loc, // Declare the thunk. auto blockTy = block.getType().castTo(); auto thunkTy = buildThunkType(block, funcTy, substFnTy, subs); - auto thunk = SGM.getOrCreateReabstractionThunk(F.getContextGenericParams(), + auto thunk = SGM.getOrCreateReabstractionThunk(F.getGenericEnvironment(), thunkTy, blockTy, funcTy, @@ -621,7 +617,7 @@ SILGenFunction::emitBlockToFunc(SILLocation loc, // Build it if necessary. if (thunk->empty()) { SILGenFunction thunkSGF(SGM, *thunk); - thunk->setContextGenericParams(F.getContextGenericParams()); + thunk->setGenericEnvironment(F.getGenericEnvironment()); auto loc = RegularLocation::getAutoGeneratedLocation(); buildBlockToFuncThunkBody(thunkSGF, loc, blockTy, funcTy); } @@ -852,7 +848,7 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &gen, auto swiftFnTy = swiftInfo.SILFnType->substGenericArgs(gen.SGM.M, mod, subs); // We must have the same context archetypes as the unthunked function. - assert(objcInfo.ContextGenericParams == swiftInfo.ContextGenericParams); + assert(objcInfo.GenericEnv == swiftInfo.GenericEnv); SmallVector bridgedArgs; bridgedArgs.reserve(objcFnTy->getParameters().size()); @@ -959,8 +955,8 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { SGM.M, SGM.M.getSwiftModule(), subs); SILType substSILTy = SILType::getPrimitiveObjectType(substTy); - // Use the same context generic params as the native entry point. - F.setContextGenericParams(nativeInfo.ContextGenericParams); + // Use the same generic environment as the native entry point. + F.setGenericEnvironment(nativeInfo.GenericEnv); auto loc = thunk.getAsRegularLocation(); loc.markAutoGenerated(); @@ -1121,8 +1117,8 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { auto nativeFnTy = F.getLoweredFunctionType(); assert(nativeFnTy == nativeCI.SILFnType); - // Use the same context generic params as the native entry point. - F.setContextGenericParams(nativeCI.ContextGenericParams); + // Use the same generic environment as the native entry point. + F.setGenericEnvironment(nativeCI.GenericEnv); // Find the foreign error convention and 'self' parameter index. Optional foreignError; @@ -1282,8 +1278,9 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { auto fnType = fn->getType().castTo(); fnType = fnType->substGenericArgs(SGM.M, SGM.SwiftModule, subs); - CanType substResultTy{ - ArchetypeBuilder::mapTypeIntoContext(fd, nativeFormalResultTy)}; + auto substResultTy = + ArchetypeBuilder::mapTypeIntoContext(fd, nativeFormalResultTy) + ->getCanonicalType(); auto resultMV = emitApply(fd, ManagedValue::forUnmanaged(fn), subs, args, fnType, diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 55559e44d8d02..9abe4e3e8848c 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -17,6 +17,7 @@ #include "RValue.h" #include "Scope.h" #include "swift/AST/AST.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Mangle.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILUndef.h" @@ -491,9 +492,10 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) { ArrayRef subs; // Call the initializer. ArrayRef forwardingSubs; - if (auto *genericParamList = ctor->getGenericParamsOfContext()) { + if (auto *genericEnv = ctor->getGenericEnvironmentOfContext()) { auto *genericSig = ctor->getGenericSignatureOfContext(); - forwardingSubs = genericParamList->getForwardingSubstitutions(genericSig); + forwardingSubs = genericEnv->getForwardingSubstitutions( + SGM.SwiftModule, genericSig); } std::tie(initVal, initTy, subs) = emitSiblingMethodRef(Loc, selfValue, initConstant, forwardingSubs); @@ -871,10 +873,11 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc, // Get the substitutions for the constructor context. ArrayRef subs; - auto *genericParams = dc->getGenericParamsOfContext(); - if (genericParams) { + auto *genericEnv = dc->getGenericEnvironmentOfContext(); + if (genericEnv) { auto *genericSig = dc->getGenericSignatureOfContext(); - subs = genericParams->getForwardingSubstitutions(genericSig); + subs = genericEnv->getForwardingSubstitutions( + SGM.SwiftModule, genericSig); } // Get the type of the initialization result, in terms diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 9c923e0a34323..362846c05b7e4 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -23,6 +23,7 @@ #include "swift/SIL/SILWitnessVisitor.h" #include "swift/SIL/TypeLowering.h" #include "swift/AST/AST.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Mangle.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" @@ -1768,34 +1769,36 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance, nameBuffer = mangler.finalize(); } - // Collect the context generic parameters for the witness. - // - // FIXME: SILFunction::ContextGenericParams needs to be a GenericSignature - // instead. - GenericParamList *witnessContextParams = nullptr; + // Collect the generic environment for the witness. + TypeSubstitutionMap witnessContextParams; // Concrete witness thunks use the context archetypes of the conformance. if (conformance) { - witnessContextParams = conformance->getGenericParams(); + if (auto *genericEnv = conformance->getGenericEnvironment()) + witnessContextParams = genericEnv->getInterfaceToArchetypeMap(); // If the requirement is generic, reparent the requirement parameters to // the conformance parameters. - if (auto reqtParams = requirementInfo.InnerGenericParams) { - // Preserve the depth of generic arguments by adding an empty outer generic - // param list if the conformance is concrete. - if (!witnessContextParams) - witnessContextParams = GenericParamList::getEmpty(getASTContext()); - - witnessContextParams - = reqtParams->cloneWithOuterParameters(getASTContext(), - witnessContextParams); + for (auto pair : requirementInfo.GenericEnv->getInterfaceToArchetypeMap()) { + // Skip the 'Self' parameter. + if (auto *archetypeTy = pair.second->getAs()) + if (archetypeTy->getSelfProtocol() != nullptr) + continue; + + auto result = witnessContextParams.insert(pair); + assert(result.second); } // Default witness thunks use the context archetypes of the requirement. } else { - witnessContextParams = requirementInfo.ContextGenericParams; + witnessContextParams = requirementInfo.GenericEnv + ->getInterfaceToArchetypeMap(); } + GenericEnvironment *witnessEnv = nullptr; + if (!witnessContextParams.empty()) + witnessEnv = GenericEnvironment::get(getASTContext(), witnessContextParams); + // If the thunked-to function is set to be always inlined, do the // same with the witness, on the theory that the user wants all // calls removed if possible, e.g. when we're able to devirtualize @@ -1814,7 +1817,7 @@ SILGenModule::emitProtocolWitness(ProtocolConformance *conformance, auto *f = M.createFunction( linkage, nameBuffer, witnessSILFnType, - witnessContextParams, SILLocation(witness.getDecl()), + witnessEnv, SILLocation(witness.getDecl()), IsNotBare, IsTransparent, isFragile, IsThunk, SILFunction::NotRelevant, InlineStrategy); @@ -1959,7 +1962,7 @@ void SILGenModule::emitDefaultWitnessTable(ProtocolDecl *protocol) { } SILFunction *SILGenModule:: -getOrCreateReabstractionThunk(GenericParamList *thunkContextParams, +getOrCreateReabstractionThunk(GenericEnvironment *genericEnv, CanSILFunctionType thunkType, CanSILFunctionType fromType, CanSILFunctionType toType, @@ -1981,11 +1984,11 @@ getOrCreateReabstractionThunk(GenericParamList *thunkContextParams, // Substitute context parameters out of the "from" and "to" types. auto fromInterfaceType = ArchetypeBuilder::mapTypeOutOfContext( - M.getSwiftModule(), thunkContextParams, fromType) + M.getSwiftModule(), genericEnv, fromType) ->getCanonicalType(); auto toInterfaceType = ArchetypeBuilder::mapTypeOutOfContext( - M.getSwiftModule(), thunkContextParams, toType) + M.getSwiftModule(), genericEnv, toType) ->getCanonicalType(); mangler.mangleType(fromInterfaceType, /*uncurry*/ 0); diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 6a6a11112c80b..4bc90570b9735 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -20,6 +20,7 @@ #include "Scope.h" #include "swift/Basic/Fallthrough.h" #include "swift/AST/AST.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILUndef.h" @@ -816,9 +817,9 @@ void SILGenFunction::emitCurryThunk(ValueDecl *vd, // Forward substitutions. ArrayRef subs; auto constantInfo = getConstantInfo(to); - if (auto gp = constantInfo.ContextGenericParams) { + if (auto *env = constantInfo.GenericEnv) { auto sig = constantInfo.SILFnType->getGenericSignature(); - subs = gp->getForwardingSubstitutions(sig); + subs = env->getForwardingSubstitutions(SGM.SwiftModule, sig); } SILValue toFn = getNextUncurryLevelRef(*this, vd, to, from.isDirectReference, diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 16685d8d5a98d..15d9d72bb83ed 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -22,9 +22,8 @@ #include "Initialization.h" #include "swift/AST/AST.h" #include "swift/AST/DiagnosticsSIL.h" -#include "swift/AST/Decl.h" -#include "swift/AST/Types.h" #include "swift/AST/DiagnosticsCommon.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/Mangle.h" #include "swift/SIL/PrettyStackTrace.h" #include "swift/SIL/SILArgument.h" @@ -1585,9 +1584,10 @@ static ArrayRef getNonMemberVarDeclSubstitutions(SILGenModule &SGM, VarDecl *var) { ArrayRef substitutions; auto *dc = var->getDeclContext(); - if (auto genericParams = dc->getGenericParamsOfContext()) { + if (auto *genericEnv = dc->getGenericEnvironmentOfContext()) { auto *genericSig = dc->getGenericSignatureOfContext(); - substitutions = genericParams->getForwardingSubstitutions(genericSig); + substitutions = genericEnv->getForwardingSubstitutions( + SGM.SwiftModule, genericSig); } return substitutions; } diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp index cf0063f6be81c..c1acbd17a2695 100644 --- a/lib/SILGen/SILGenMaterializeForSet.cpp +++ b/lib/SILGen/SILGenMaterializeForSet.cpp @@ -98,7 +98,7 @@ struct MaterializeForSetEmitter { ArrayRef WitnessSubs; CanGenericSignature GenericSig; - GenericParamList *GenericParams; + GenericEnvironment *GenericEnv; // Assume that we don't need to reabstract 'self'. Right now, // that's always true; if we ever reabstract Optional (or other @@ -128,7 +128,7 @@ struct MaterializeForSetEmitter { WitnessStorage(witness->getAccessorStorageDecl()), WitnessStoragePattern(AbstractionPattern::getInvalid()), WitnessSubs(subs), - GenericParams(nullptr), + GenericEnv(nullptr), SelfInterfaceType(selfInterfaceType->getCanonicalType()), SubstSelfType(selfType->getCanonicalType()), TheAccessSemantics(AccessSemantics::Ordinary), @@ -178,11 +178,11 @@ struct MaterializeForSetEmitter { if (conformance) { if (auto signature = conformance->getGenericSignature()) emitter.GenericSig = signature->getCanonicalSignature(); - emitter.GenericParams = conformance->getGenericParams(); + emitter.GenericEnv = conformance->getGenericEnvironment(); } else { auto signature = requirement->getGenericSignatureOfContext(); emitter.GenericSig = signature->getCanonicalSignature(); - emitter.GenericParams = requirement->getGenericParamsOfContext(); + emitter.GenericEnv = requirement->getGenericEnvironmentOfContext(); } emitter.RequirementStorage = requirement->getAccessorStorageDecl(); @@ -218,7 +218,7 @@ struct MaterializeForSetEmitter { if (auto signature = witness->getGenericSignatureOfContext()) emitter.GenericSig = signature->getCanonicalSignature(); - emitter.GenericParams = constantInfo.ContextGenericParams; + emitter.GenericEnv = constantInfo.GenericEnv; emitter.RequirementStorage = emitter.WitnessStorage; emitter.RequirementStoragePattern = emitter.WitnessStoragePattern; @@ -552,7 +552,7 @@ SILFunction *MaterializeForSetEmitter::createCallback(SILFunction &F, F.isTransparent(), F.isFragile()); - callback->setContextGenericParams(GenericParams); + callback->setGenericEnvironment(GenericEnv); callback->setDebugScope(new (SGM.M) SILDebugScope(Witness, callback)); PrettyStackTraceSILFunction X("silgen materializeForSet callback", callback); diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 21b8c4df17769..8f47b27f8bb85 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -2450,7 +2450,7 @@ static ManagedValue createThunk(SILGenFunction &gen, auto thunkType = gen.buildThunkType(fn, expectedType, substFnType, substitutions); auto thunk = gen.SGM.getOrCreateReabstractionThunk( - gen.F.getContextGenericParams(), + gen.F.getGenericEnvironment(), thunkType, fn.getType().castTo(), expectedType, @@ -2459,7 +2459,7 @@ static ManagedValue createThunk(SILGenFunction &gen, // Build it if necessary. if (thunk->empty()) { // Borrow the context archetypes from the enclosing function. - thunk->setContextGenericParams(gen.F.getContextGenericParams()); + thunk->setGenericEnvironment(gen.F.getGenericEnvironment()); SILGenFunction thunkSGF(gen.SGM, *thunk); auto loc = RegularLocation::getAutoGeneratedLocation(); buildThunkBody(thunkSGF, loc, @@ -2679,8 +2679,8 @@ SILGenFunction::emitVTableThunk(SILDeclRef derived, auto fTy = implFn->getLoweredFunctionType(); ArrayRef subs; - if (auto context = fd->getGenericParamsOfContext()) { - F.setContextGenericParams(context); + if (auto *genericEnv = fd->getGenericEnvironment()) { + F.setGenericEnvironment(genericEnv); subs = getForwardingSubstitutions(); fTy = fTy->substGenericArgs(SGM.M, SGM.SwiftModule, subs); @@ -2824,7 +2824,7 @@ static CanType dropLastElement(CanType type) { static void addConformanceToSubstitutionMap(SILGenModule &SGM, TypeSubstitutionMap &subs, - GenericParamList *context, + GenericEnvironment *genericEnv, CanType base, const ProtocolConformance *conformance) { conformance->forEachTypeWitness(nullptr, [&](AssociatedTypeDecl *assocTy, @@ -2834,14 +2834,14 @@ static void addConformanceToSubstitutionMap(SILGenModule &SGM, CanDependentMemberType::get(base, assocTy, SGM.getASTContext()); auto replacement = sub.getReplacement()->getCanonicalType(); replacement = ArchetypeBuilder::mapTypeOutOfContext(SGM.M.getSwiftModule(), - context, + genericEnv, replacement) ->getCanonicalType(); subs.insert({depTy.getPointer(), replacement}); for (auto conformance : sub.getConformances()) { if (conformance.isAbstract()) continue; - addConformanceToSubstitutionMap(SGM, subs, context, + addConformanceToSubstitutionMap(SGM, subs, genericEnv, depTy, conformance.getConcrete()); } return false; @@ -2860,7 +2860,8 @@ substSelfTypeIntoProtocolRequirementType(CanGenericFunctionType reqtTy, TypeSubstitutionMap subs; subs.insert({selfParamTy.getPointer(), conformance->getInterfaceType() ->getCanonicalType()}); - addConformanceToSubstitutionMap(*this, subs, conformance->getGenericParams(), + addConformanceToSubstitutionMap(*this, subs, + conformance->getGenericEnvironment(), selfParamTy, conformance); // Drop requirements rooted in the applied generic parameters. diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index e2532ae261ede..443f14a6a808b 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -93,7 +93,7 @@ SILGenModule::emitVTableMethod(SILDeclRef derived, SILDeclRef base) { auto thunk = M.createFunction(SILLinkage::Private, name, overrideInfo.SILFnType, - derivedDecl->getGenericParams(), loc, IsBare, + derivedDecl->getGenericEnvironment(), loc, IsBare, IsNotTransparent, IsNotFragile); thunk->setDebugScope(new (M) SILDebugScope(loc, thunk)); diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp index e1c0e3f4fb87f..748f8b8078b9b 100644 --- a/lib/SILOptimizer/IPO/CapturePromotion.cpp +++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp @@ -46,6 +46,7 @@ #include "swift/SIL/SILCloner.h" #include "swift/SIL/TypeSubstCloner.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/AST/GenericEnvironment.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" @@ -444,7 +445,7 @@ ClosureCloner::initCloned(SILFunction *Orig, IsFragile_t Fragile, assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned"); auto *Fn = M.createFunction( - Orig->getLinkage(), ClonedName, SubstTy, Orig->getContextGenericParams(), + Orig->getLinkage(), ClonedName, SubstTy, Orig->getGenericEnvironment(), Orig->getLocation(), Orig->isBare(), IsNotTransparent, Fragile, Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig, Orig->getDebugScope()); @@ -866,7 +867,7 @@ constructClonedFunction(PartialApplyInst *PAI, FunctionRefInst *FRI, ArrayRef ApplySubs = PAI->getSubstitutions(); auto genericSig = F->getLoweredFunctionType()->getGenericSignature(); - auto *genericParams = F->getContextGenericParams(); + auto *genericParams = F->getGenericEnvironment(); if (!ApplySubs.empty()) { InterfaceSubs = genericSig->getSubstitutionMap(ApplySubs); diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index 85297ce068bba..bac3080eb6d80 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -548,7 +548,7 @@ ClosureSpecCloner::initCloned(const CallSiteDescriptor &CallSiteDesc, // original function was de-serialized) and would not be code-gen'd. getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName, ClonedTy, - ClosureUser->getContextGenericParams(), ClosureUser->getLocation(), + ClosureUser->getGenericEnvironment(), ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(), CallSiteDesc.isFragile(), ClosureUser->isThunk(), ClosureUser->getClassVisibility(), ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(), diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp index 8ac5794c78957..8dd4032b4e67d 100644 --- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp +++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp @@ -14,6 +14,7 @@ #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsSIL.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/SILOptimizer/Utils/Devirtualize.h" #include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/Utils/SILInliner.h" @@ -435,7 +436,7 @@ runOnFunctionRecursively(SILFunction *F, FullApplySite AI, ApplySubs.insert(ApplySubs.end(), PAISubs.begin(), PAISubs.end()); } - if (auto *params = CalleeFunction->getContextGenericParams()) { + if (auto *params = CalleeFunction->getGenericEnvironment()) { auto sig = CalleeFunction->getLoweredFunctionType() ->getGenericSignature(); params->getSubstitutionMap(F->getModule().getSwiftModule(), diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp index 3b4300549c47d..20daafed4aa3c 100644 --- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp +++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp @@ -566,7 +566,7 @@ PromotedParamCloner::initCloned(SILFunction *Orig, IsFragile_t Fragile, && "SILFunction missing DebugScope"); assert(!Orig->isGlobalInit() && "Global initializer cannot be cloned"); auto *Fn = M.createFunction( - SILLinkage::Shared, ClonedName, ClonedTy, Orig->getContextGenericParams(), + SILLinkage::Shared, ClonedName, ClonedTy, Orig->getGenericEnvironment(), Orig->getLocation(), Orig->isBare(), IsNotTransparent, Fragile, Orig->isThunk(), Orig->getClassVisibility(), Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig, Orig->getDebugScope()); diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index 737dbf2f4eaa0..9c54a3e2d95dd 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -16,6 +16,7 @@ #include "swift/SILOptimizer/Utils/Generics.h" #include "swift/SILOptimizer/Utils/GenericCloner.h" #include "swift/SIL/DebugUtils.h" +#include "swift/AST/GenericEnvironment.h" using namespace swift; @@ -187,13 +188,13 @@ GenericFuncSpecializer::GenericFuncSpecializer(SILFunction *GenericFunc, assert(GenericFunc->isDefinition() && "Expected definition to specialize!"); - if (auto *params = GenericFunc->getContextGenericParams()) { + if (auto *env = GenericFunc->getGenericEnvironment()) { auto sig = GenericFunc->getLoweredFunctionType()->getGenericSignature(); ArchetypeConformanceMap conformanceMap; - params->getSubstitutionMap(M.getSwiftModule(), sig, - ParamSubs, ContextSubs, - conformanceMap); + env->getSubstitutionMap(M.getSwiftModule(), sig, + ParamSubs, ContextSubs, + conformanceMap); } Mangle::Mangler Mangler; diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 08b0253bcff65..f21defe4aed3f 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -21,6 +21,7 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/Availability.h" #include "swift/AST/Expr.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/ParameterList.h" #include "swift/Basic/Defer.h" #include "llvm/ADT/SmallString.h" @@ -1134,6 +1135,17 @@ static FuncDecl *completeLazyPropertyGetter(VarDecl *VD, VarDecl *Storage, return Get; } +static ArrayRef +getForwardingSubstitutions(DeclContext *DC) { + if (auto *env = DC->getGenericEnvironmentOfContext()) { + auto *sig = DC->getGenericSignatureOfContext(); + return env->getForwardingSubstitutions( + DC->getParentModule(), sig); + } + + return { }; +} + void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD, VarDecl *BehaviorStorage, FuncDecl *DefaultInitStorage, @@ -1270,12 +1282,7 @@ void TypeChecker::completePropertyBehaviorStorage(VarDecl *VD, addTrivialAccessorsToStorage(Storage, *this); // Add the witnesses to the conformance. - ArrayRef MemberSubs; - if (auto *sig = DC->getGenericSignatureOfContext()) { - MemberSubs = DC->getGenericParamsOfContext() - ->getForwardingSubstitutions(sig); - } - + auto MemberSubs = getForwardingSubstitutions(DC); BehaviorConformance->setWitness(BehaviorStorage, ConcreteDeclRef(Context, Storage, MemberSubs)); BehaviorConformance->setWitness(BehaviorStorage->getGetter(), @@ -1303,6 +1310,7 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD, ->getResult(); GenericSignature *genericSig = nullptr; + GenericEnvironment *genericEnv = nullptr; TypeSubstitutionMap interfaceMap = sig->getSubstitutionMap(SelfInterfaceSubs); auto SubstInterfaceTy = ParameterTy.subst(VD->getModuleContext(), @@ -1321,6 +1329,7 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD, if (DC->isTypeContext()) { if (DC->isGenericContext()) { genericSig = DC->getGenericSignatureOfContext(); + genericEnv = DC->getGenericEnvironmentOfContext(); SubstInterfaceTy = GenericFunctionType::get(genericSig, DC->getSelfInterfaceType(), SubstInterfaceTy, @@ -1398,6 +1407,7 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD, Parameter->setInterfaceType(SubstInterfaceTy); Parameter->setGenericSignature(genericSig); + Parameter->setGenericEnvironment(genericEnv); // Mark the method to be final, implicit, and private. In a class, this // prevents it from being dynamically dispatched. @@ -1439,12 +1449,7 @@ void TypeChecker::completePropertyBehaviorParameter(VarDecl *VD, addMemberToContextIfNeeded(Parameter, DC); // Add the witnesses to the conformance. - ArrayRef MemberSubs; - if (auto *sig = DC->getGenericSignatureOfContext()) { - MemberSubs = DC->getGenericParamsOfContext() - ->getForwardingSubstitutions(sig); - } - + auto MemberSubs = getForwardingSubstitutions(DC); BehaviorConformance->setWitness(BehaviorParameter, ConcreteDeclRef(Context, Parameter, MemberSubs)); } @@ -2132,6 +2137,7 @@ swift::createDesignatedInitOverride(TypeChecker &tc, // Set the interface type of the initializer. ctor->setGenericSignature(classDecl->getGenericSignatureOfContext()); + ctor->setGenericEnvironment(classDecl->getGenericEnvironmentOfContext()); tc.configureInterfaceType(ctor); // Set the contextual type of the initializer. This will go away one day. diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 4ee22b100bbe0..207b8391a3035 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -258,6 +258,7 @@ deriveEquatable_enum_eq(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) { Type selfIfaceTy = eqDecl->computeInterfaceSelfType(false); if (auto genericSig = parentDC->getGenericSignatureOfContext()) { eqDecl->setGenericSignature(genericSig); + eqDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext()); Type enumIfaceTy = parentDC->getDeclaredInterfaceType(); TupleTypeElt ifaceParamElts[] = { @@ -411,6 +412,7 @@ deriveHashable_enum_hashValue(TypeChecker &tc, Decl *parentDecl, Type selfIfaceType = getterDecl->computeInterfaceSelfType(false); if (auto sig = parentDC->getGenericSignatureOfContext()) { getterDecl->setGenericSignature(sig); + getterDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext()); interfaceType = GenericFunctionType::get(sig, selfIfaceType, methodType, AnyFunctionType::ExtInfo()); } else diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index 2a87972ab6683..d1dd8051d26d3 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -320,6 +320,7 @@ static ConstructorDecl *deriveRawRepresentable_init(TypeChecker &tc, Type initIfaceType; if (auto sig = parentDC->getGenericSignatureOfContext()) { initDecl->setGenericSignature(sig); + initDecl->setGenericEnvironment(parentDC->getGenericEnvironmentOfContext()); allocIfaceType = GenericFunctionType::get(sig, selfInterfaceType, interfaceType, diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index eaccf5a0cc352..7f939bfb1bb0e 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -148,6 +148,8 @@ FuncDecl *DerivedConformance::declareDerivedPropertyGetter(TypeChecker &tc, Type selfInterfaceType = getterDecl->computeInterfaceSelfType(false); if (auto sig = parentDC->getGenericSignatureOfContext()) { getterDecl->setGenericSignature(sig); + getterDecl->setGenericEnvironment( + parentDC->getGenericEnvironmentOfContext()); interfaceType = GenericFunctionType::get(sig, selfInterfaceType, interfaceType, FunctionType::ExtInfo()); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 999b1b40140b1..6ab832aa27627 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -377,7 +377,17 @@ void TypeChecker::checkInheritanceClause(Decl *decl, continue; // Retrieve the interface type for this inherited type. - if (inheritedTy->hasArchetype()) + // + // If we have a generic parameter, mapTypeOutOfContext() might not + // work yet, if we're calling this while building the generic + // signature. However, we're also not storing inheritedTy back + // anywhere, so it's OK to leave it as an archetype. + // + // FIXME: Ideally, we wouldn't have code paths that take a mix + // of archetypes and interface types. Other than generic parameters, + // the only time we get an interface type here is with invalid + // circular cases. That should be diagnosed elsewhere. + if (inheritedTy->hasArchetype() && !isa(decl)) inheritedTy = ArchetypeBuilder::mapTypeOutOfContext(DC, inheritedTy); // Check whether we inherited from the same type twice. @@ -696,9 +706,10 @@ ArchetypeBuilder TypeChecker::createArchetypeBuilder(Module *mod) { } /// Expose TypeChecker's handling of GenericParamList to SIL parsing. -GenericSignature *TypeChecker::handleSILGenericParams( - GenericParamList *genericParams, - DeclContext *DC) { +std::pair +TypeChecker::handleSILGenericParams(GenericParamList *genericParams, + DeclContext *DC) { + SmallVector nestedList; for (; genericParams; genericParams = genericParams->getOuterParameters()) { nestedList.push_back(genericParams); @@ -712,23 +723,26 @@ GenericSignature *TypeChecker::handleSILGenericParams( // Since the innermost GenericParamList is in the beginning of the vector, // we process in reverse order to handle the outermost list first. GenericSignature *parentSig = nullptr; + GenericEnvironment *parentEnv = nullptr; + for (unsigned i = 0, e = nestedList.size(); i < e; i++) { auto genericParams = nestedList.rbegin()[i]; bool invalid = false; auto *genericSig = validateGenericSignature(genericParams, DC, parentSig, nullptr, invalid); if (invalid) - return nullptr; + return std::make_pair(nullptr, nullptr); revertGenericParamList(genericParams); ArchetypeBuilder builder(*DC->getParentModule(), Diags); checkGenericParamList(&builder, genericParams, parentSig); - finalizeGenericParamList(builder, genericParams, DC); - + parentEnv = finalizeGenericParamList(builder, genericParams, + genericSig, DC); parentSig = genericSig; } - return parentSig; + + return std::make_pair(parentSig, parentEnv); } /// Check whether the given type representation will be @@ -2495,7 +2509,7 @@ static void checkEnumRawValues(TypeChecker &TC, EnumDecl *ED) { return; } - if (ED->getGenericParamsOfContext() != nullptr) + if (ED->getGenericEnvironmentOfContext() != nullptr) rawTy = ArchetypeBuilder::mapTypeIntoContext(ED, rawTy); if (rawTy->is()) return; @@ -4698,7 +4712,8 @@ class DeclChecker : public DeclVisitor { gp->setOuterParameters(FD->getDeclContext()->getGenericParamsOfContext()); if (TC.validateGenericFuncSignature(FD)) { - TC.markInvalidGenericSignature(FD); + auto *env = TC.markInvalidGenericSignature(FD); + FD->setGenericEnvironment(env); } else { // Create a fresh archetype builder. ArchetypeBuilder builder = @@ -4721,14 +4736,18 @@ class DeclChecker : public DeclVisitor { TC.revertGenericFuncSignature(FD); // Assign archetypes. - TC.finalizeGenericParamList(builder, gp, FD); + auto *env = TC.finalizeGenericParamList(builder, gp, nullptr, FD); + FD->setGenericEnvironment(env); } - } else if (FD->getDeclContext()->isGenericContext()) { + } else if (FD->getDeclContext()->getGenericSignatureOfContext()) { if (TC.validateGenericFuncSignature(FD)) { - TC.markInvalidGenericSignature(FD); + auto *env = TC.markInvalidGenericSignature(FD); + FD->setGenericEnvironment(env); } else if (!FD->hasType()) { // Revert all of the types within the signature of the function. TC.revertGenericFuncSignature(FD); + FD->setGenericEnvironment( + FD->getDeclContext()->getGenericEnvironmentOfContext()); } else { // Recursively satisfied. // FIXME: This is an awful hack. @@ -4741,7 +4760,7 @@ class DeclChecker : public DeclVisitor { if (semaFuncDecl(FD, &resolver)) return; - if (!FD->isGenericContext()) + if (!FD->getGenericSignatureOfContext()) TC.configureInterfaceType(FD); if (FD->isInvalid()) @@ -6127,7 +6146,7 @@ class DeclChecker : public DeclVisitor { /// Compute the interface type of the given enum element. void computeEnumElementInterfaceType(EnumElementDecl *elt) { auto enumDecl = cast(elt->getDeclContext()); - assert(enumDecl->isGenericContext() && "Not a generic enum"); + assert(enumDecl->getGenericSignatureOfContext() && "Not a generic enum"); // Build the generic function type. auto funcTy = elt->getType()->castTo(); @@ -6223,7 +6242,7 @@ class DeclChecker : public DeclVisitor { // case the enclosing enum type was illegally declared inside of a generic // context. (In that case, we'll post a diagnostic while visiting the // parent enum.) - if (EED->getDeclContext()->isGenericContext()) + if (EED->getDeclContext()->getGenericSignatureOfContext()) computeEnumElementInterfaceType(EED); // Require the carried type to be materializable. @@ -6384,7 +6403,8 @@ class DeclChecker : public DeclVisitor { gp->setOuterParameters(CD->getDeclContext()->getGenericParamsOfContext()); if (TC.validateGenericFuncSignature(CD)) { - TC.markInvalidGenericSignature(CD); + auto *env = TC.markInvalidGenericSignature(CD); + CD->setGenericEnvironment(env); } else { ArchetypeBuilder builder = TC.createArchetypeBuilder(CD->getModuleContext()); @@ -6399,14 +6419,19 @@ class DeclChecker : public DeclVisitor { TC.revertGenericFuncSignature(CD); // Assign archetypes. - TC.finalizeGenericParamList(builder, gp, CD); + auto *env = TC.finalizeGenericParamList(builder, gp, nullptr, CD); + CD->setGenericEnvironment(env); } - } else if (CD->getDeclContext()->isGenericContext()) { + } else if (CD->getDeclContext()->getGenericSignatureOfContext()) { if (TC.validateGenericFuncSignature(CD)) { - TC.markInvalidGenericSignature(CD); + auto *env = TC.markInvalidGenericSignature(CD); + CD->setGenericEnvironment(env); } else { // Revert all of the types within the signature of the constructor. TC.revertGenericFuncSignature(CD); + + CD->setGenericEnvironment( + CD->getDeclContext()->getGenericEnvironmentOfContext()); } } @@ -6419,7 +6444,7 @@ class DeclChecker : public DeclVisitor { configureConstructorType(CD, SelfTy, CD->getParameterList(1)->getType(TC.Context)); - if (!CD->isGenericContext()) + if (!CD->getGenericSignatureOfContext()) TC.configureInterfaceType(CD); } @@ -6554,8 +6579,11 @@ class DeclChecker : public DeclVisitor { Type SelfTy = configureImplicitSelf(TC, DD); - if (DD->getDeclContext()->isGenericContext()) + if (DD->getDeclContext()->getGenericSignatureOfContext()) { TC.validateGenericFuncSignature(DD); + DD->setGenericEnvironment( + DD->getDeclContext()->getGenericEnvironmentOfContext()); + } if (semaFuncParamPatterns(DD)) { DD->overwriteType(ErrorType::get(TC.Context)); @@ -6563,7 +6591,7 @@ class DeclChecker : public DeclVisitor { DD->setInvalid(); } - if (!DD->isGenericContext()) + if (!DD->getGenericSignatureOfContext()) TC.configureInterfaceType(DD); if (!DD->hasType()) { @@ -7328,8 +7356,7 @@ void TypeChecker::validateAccessibility(ValueDecl *D) { /// the parameter lists within the extension. static Type checkExtensionGenericParams( TypeChecker &tc, ExtensionDecl *ext, - Type type, GenericParamList *genericParams, - GenericSignature *&sig) { + Type type, GenericParamList *genericParams) { // Find the nominal type declaration and its parent type. Type parentType; NominalTypeDecl *nominal; @@ -7352,8 +7379,7 @@ static Type checkExtensionGenericParams( tc, ext, parentType, nominal->getGenericParams() ? genericParams->getOuterParameters() - : genericParams, - sig); + : genericParams); if (!newParentType) return Type(); } @@ -7396,9 +7422,14 @@ static Type checkExtensionGenericParams( // Validate the generic type signature. bool invalid = false; - sig = tc.validateGenericSignature(genericParams, ext->getDeclContext(), - nullptr, inferExtendedTypeReqs, invalid); + GenericSignature *sig = tc.validateGenericSignature( + genericParams, ext->getDeclContext(), + nullptr, inferExtendedTypeReqs, invalid); + ext->setGenericSignature(sig); + if (invalid) { + auto *env = tc.markInvalidGenericSignature(ext); + ext->setGenericEnvironment(env); return nullptr; } @@ -7408,7 +7439,9 @@ static Type checkExtensionGenericParams( auto *parentSig = ext->getDeclContext()->getGenericSignatureOfContext(); tc.checkGenericParamList(&builder, genericParams, parentSig); inferExtendedTypeReqs(builder); - tc.finalizeGenericParamList(builder, genericParams, ext); + + auto *env = tc.finalizeGenericParamList(builder, genericParams, nullptr, ext); + ext->setGenericEnvironment(env); if (isa(nominal)) { // Retain type sugar if it's there. @@ -7475,24 +7508,28 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) { assert(genericParams && "bindExtensionDecl didn't set generic params?"); // Check generic parameters. - GenericSignature *sig = nullptr; extendedType = checkExtensionGenericParams(*this, ext, ext->getExtendedType(), - ext->getGenericParams(), - sig); + ext->getGenericParams()); if (!extendedType) { ext->setInvalid(); ext->getExtendedTypeLoc().setInvalidType(Context); return; } - ext->setGenericSignature(sig); ext->getExtendedTypeLoc().setType(extendedType); return; } // If we're extending a protocol, check the generic parameters. - if (auto proto = extendedType->getAs()) { + // + // Canonicalize the type to work around the fact that getAs<> cannot + // "look through" protocol where X and Y both desugar to the same + // thing. + // + // FIXME: Probably the above comes up elsewhere, perhaps getAs<>() + // should be fixed. + if (auto proto = extendedType->getCanonicalType()->getAs()) { if (!isa(extendedType.getPointer()) && proto->getDecl()->getParentModule() == ext->getParentModule()) { // Protocols in the same module cannot be extended via a typealias; @@ -7505,18 +7542,14 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) { return; } - GenericSignature *sig = nullptr; - extendedType = checkExtensionGenericParams(*this, ext, - ext->getExtendedType(), - ext->getGenericParams(), - sig); + extendedType = checkExtensionGenericParams(*this, ext, proto, + ext->getGenericParams()); if (!extendedType) { ext->setInvalid(); ext->getExtendedTypeLoc().setInvalidType(Context); return; } - ext->setGenericSignature(sig); ext->getExtendedTypeLoc().setType(extendedType); // Speculatively ban extension of AnyObject; it won't be a @@ -7529,6 +7562,8 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) { } return; } + + assert(extendedType->is()); } ArrayRef diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 3ef28587c5a04..53a79640f4440 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -471,33 +471,36 @@ static Type getResultType(TypeChecker &TC, FuncDecl *fn, Type resultType) { return resultType; } -void TypeChecker::markInvalidGenericSignature(ValueDecl *VD) { - GenericParamList *genericParams; - if (auto *AFD = dyn_cast(VD)) - genericParams = AFD->getGenericParams(); - else - genericParams = cast(VD)->getGenericParams(); - +GenericEnvironment * +TypeChecker::markInvalidGenericSignature(DeclContext *DC) { // If there aren't any generic parameters at this level, we're done. - if (genericParams == nullptr) - return; + if (!DC->isInnermostContextGeneric()) + return nullptr; + + GenericParamList *genericParams = DC->getGenericParamsOfContext(); + GenericSignature *genericSig = DC->getGenericSignatureOfContext(); + + // Build new archetypes without any generic requirements. + DeclContext *parentDC = DC->getParent(); + auto builder = createArchetypeBuilder(parentDC->getParentModule()); - DeclContext *DC = VD->getDeclContext(); - ArchetypeBuilder builder = createArchetypeBuilder(DC->getParentModule()); + auto parentSig = parentDC->getGenericSignatureOfContext(); - if (auto sig = DC->getGenericSignatureOfContext()) - builder.addGenericSignature(sig, true); + if (parentSig != nullptr) + builder.addGenericSignature(parentSig, true); // Visit each of the generic parameters. for (auto param : *genericParams) builder.addGenericParameter(param); // Wire up the archetypes. + auto genericEnv = builder.getGenericEnvironment( + genericSig->getGenericParams()); + for (auto GP : *genericParams) GP->setArchetype(builder.getArchetype(GP)); - genericParams->setAllArchetypes( - Context.AllocateCopy(builder.getAllArchetypes())); + return genericEnv; } bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { @@ -540,7 +543,7 @@ bool TypeChecker::validateGenericFuncSignature(AbstractFunctionDecl *func) { auto sig = builder.getGenericSignature(allGenericParams); // Debugging of the archetype builder and generic signature generation. - if (sig && Context.LangOpts.DebugGenericSignatures) { + if (Context.LangOpts.DebugGenericSignatures) { func->dumpRef(llvm::errs()); llvm::errs() << "\n"; builder.dump(llvm::errs()); @@ -789,9 +792,11 @@ static void revertDependentTypeLoc(TypeLoc &tl) { /// Finalize the given generic parameter list, assigning archetypes to /// the generic parameters. -void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, - GenericParamList *genericParams, - DeclContext *dc) { +GenericEnvironment * +TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, + GenericParamList *genericParams, + GenericSignature *genericSig, + DeclContext *dc) { Accessibility access; if (auto *fd = dyn_cast(dc)) access = fd->getFormalAccess(); @@ -802,14 +807,17 @@ void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, access = std::max(access, Accessibility::Internal); // Wire up the archetypes. + if (genericSig == nullptr) + genericSig = dc->getGenericSignatureOfContext(); + auto genericEnv = builder.getGenericEnvironment( + genericSig->getGenericParams()); + for (auto GP : *genericParams) { GP->setArchetype(builder.getArchetype(GP)); checkInheritanceClause(GP); if (!GP->hasAccessibility()) GP->setAccessibility(access); } - genericParams->setAllArchetypes( - Context.AllocateCopy(builder.getAllArchetypes())); #ifndef NDEBUG // Record archetype contexts. @@ -859,6 +867,8 @@ void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, break; } } + + return genericEnv; } /// Revert the dependent types within the given generic parameter list. @@ -903,13 +913,14 @@ bool TypeChecker::validateGenericTypeSignature(GenericTypeDecl *typeDecl) { auto *gp = typeDecl->getGenericParams(); auto *dc = typeDecl->getDeclContext(); - auto sig = validateGenericSignature(gp, dc, nullptr, nullptr, invalid); + auto *sig = validateGenericSignature(gp, dc, nullptr, nullptr, invalid); assert(sig->getInnermostGenericParams().size() == typeDecl->getGenericParams()->size()); typeDecl->setGenericSignature(sig); if (invalid) { - markInvalidGenericSignature(typeDecl); + auto *env = markInvalidGenericSignature(typeDecl); + typeDecl->setGenericEnvironment(env); return invalid; } @@ -919,7 +930,9 @@ bool TypeChecker::validateGenericTypeSignature(GenericTypeDecl *typeDecl) { createArchetypeBuilder(typeDecl->getModuleContext()); auto *parentSig = dc->getGenericSignatureOfContext(); checkGenericParamList(&builder, gp, parentSig); - finalizeGenericParamList(builder, gp, typeDecl); + + auto *env = finalizeGenericParamList(builder, gp, nullptr, typeDecl); + typeDecl->setGenericEnvironment(env); return invalid; } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c9d409867f515..b0104cb55783a 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -292,19 +292,12 @@ Type TypeChecker::resolveTypeInContext( // extension MyProtocol where Self : YourProtocol { ... } if (parentDC->getAsProtocolExtensionContext()) { auto ED = cast(parentDC); - if (auto genericParams = ED->getGenericParams()) { - for (auto req : genericParams->getTrailingRequirements()) { - // We might be resolving 'req.getSubject()' itself. - // This whole case feels like a hack -- there should be a - // more principled way to represent extensions of protocol - // compositions. - if (req.getKind() == RequirementReprKind::TypeConstraint) { - if (!req.getSubject() || - !req.getSubject()->is() || - !req.getSubject()->castTo()->getSelfProtocol()) - continue; - - stack.push_back(req.getConstraint()); + if (auto genericSig = ED->getGenericSignature()) { + for (auto req : genericSig->getRequirements()) { + if (req.getKind() == RequirementKind::Conformance || + req.getKind() == RequirementKind::Superclass) { + if (req.getFirstType()->isEqual(ED->getSelfInterfaceType())) + stack.push_back(req.getSecondType()); } } } @@ -2131,11 +2124,11 @@ Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr, } // SIL uses polymorphic function types to resolve overloaded member functions. - if (auto genericParams = repr->getGenericParams()) { + if (auto genericEnv = repr->getGenericEnvironment()) { auto *genericSig = repr->getGenericSignature(); assert(genericSig != nullptr && "Did not call handleSILGenericParams()?"); - inputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericParams, inputTy); - outputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericParams, outputTy); + inputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, inputTy); + outputTy = ArchetypeBuilder::mapTypeOutOfContext(M, genericEnv, outputTy); return GenericFunctionType::get(genericSig, inputTy, outputTy, extInfo); } @@ -2224,24 +2217,24 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, SmallVector interfaceParams; SmallVector interfaceResults; Optional interfaceErrorResult; - if (auto *genericParams = repr->getGenericParams()) { + if (auto *genericEnv = repr->getGenericEnvironment()) { genericSig = repr->getGenericSignature()->getCanonicalSignature(); for (auto ¶m : params) { auto transParamType = ArchetypeBuilder::mapTypeOutOfContext( - M, genericParams, param.getType())->getCanonicalType(); + M, genericEnv, param.getType())->getCanonicalType(); interfaceParams.push_back(param.getWithType(transParamType)); } for (auto &result : results) { auto transResultType = ArchetypeBuilder::mapTypeOutOfContext( - M, genericParams, result.getType())->getCanonicalType(); + M, genericEnv, result.getType())->getCanonicalType(); interfaceResults.push_back(result.getWithType(transResultType)); } if (errorResult) { auto transErrorResultType = ArchetypeBuilder::mapTypeOutOfContext( - M, genericParams, errorResult->getType())->getCanonicalType(); + M, genericEnv, errorResult->getType())->getCanonicalType(); interfaceErrorResult = errorResult->getWithType(transErrorResultType); } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index d3c5f2b012947..c938524530a75 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -706,9 +706,10 @@ bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T, } /// Expose TypeChecker's handling of GenericParamList to SIL parsing. -GenericSignature *swift::handleSILGenericParams(ASTContext &Ctx, - GenericParamList *genericParams, - DeclContext *DC) { +std::pair +swift::handleSILGenericParams(ASTContext &Ctx, + GenericParamList *genericParams, + DeclContext *DC) { return TypeChecker(Ctx).handleSILGenericParams(genericParams, DC); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 0694cb74c3dd5..05b146a52f626 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -731,8 +731,9 @@ class TypeChecker final : public LazyResolver { void checkUnsupportedProtocolType(Stmt *stmt); /// Expose TypeChecker's handling of GenericParamList to SIL parsing. - GenericSignature *handleSILGenericParams(GenericParamList *genericParams, - DeclContext *DC); + std::pair + handleSILGenericParams(GenericParamList *genericParams, + DeclContext *DC); /// \brief Resolves a TypeRepr to a type. /// @@ -996,7 +997,7 @@ class TypeChecker final : public LazyResolver { bool isProtocolExtensionUsable(DeclContext *dc, Type type, ExtensionDecl *protocolExtension) override; - void markInvalidGenericSignature(ValueDecl *VD); + GenericEnvironment *markInvalidGenericSignature(DeclContext *dc); /// Configure the interface type of a function declaration. void configureInterfaceType(AbstractFunctionDecl *func); @@ -1044,9 +1045,10 @@ class TypeChecker final : public LazyResolver { /// Finalize the given generic parameter list, assigning archetypes to /// the generic parameters. - void finalizeGenericParamList(ArchetypeBuilder &builder, - GenericParamList *genericParams, - DeclContext *dc); + GenericEnvironment *finalizeGenericParamList(ArchetypeBuilder &builder, + GenericParamList *genericParams, + GenericSignature *genericSig, + DeclContext *dc); /// Validate the signature of a generic type. /// diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 9e83da8e67b07..ff1ec85d28ef1 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -15,6 +15,7 @@ #include "swift/AST/AST.h" #include "swift/AST/ASTContext.h" #include "swift/AST/ForeignErrorConvention.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/Parse/Parser.h" @@ -633,8 +634,7 @@ ModuleFile::maybeReadSubstitution(llvm::BitstreamCursor &cursor) { GenericParamList * ModuleFile::maybeGetOrReadGenericParams(serialization::DeclID genericContextID, - DeclContext *DC, - llvm::BitstreamCursor &Cursor) { + DeclContext *DC) { if (genericContextID) { Decl *genericContext = getDecl(genericContextID); assert(genericContext && "loading PolymorphicFunctionType before its decl"); @@ -647,93 +647,44 @@ ModuleFile::maybeGetOrReadGenericParams(serialization::DeclID genericContextID, return ext->getGenericParams(); llvm_unreachable("only functions and nominals can provide generic params"); } else { - return maybeReadGenericParams(DC, Cursor); + return maybeReadGenericParams(DC); } } GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, - llvm::BitstreamCursor &Cursor, GenericParamList *outerParams) { using namespace decls_block; assert(DC && "need a context for the decls in the list"); - BCOffsetRAII lastRecordOffset(Cursor); + BCOffsetRAII lastRecordOffset(DeclTypeCursor); SmallVector scratch; StringRef blobData; - auto next = Cursor.advance(AF_DontPopBlockAtEnd); + auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (next.Kind != llvm::BitstreamEntry::Record) return nullptr; - // Read the raw archetype IDs into a different scratch buffer - // because we need to keep this alive for longer. - SmallVector rawArchetypeIDsBuffer; - unsigned kind = Cursor.readRecord(next.ID, rawArchetypeIDsBuffer, &blobData); + unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData); if (kind != GENERIC_PARAM_LIST) return nullptr; - // Read in the raw-archetypes buffer, but don't try to consume it yet. - ArrayRef rawArchetypeIDs; - GenericParamListLayout::readRecord(rawArchetypeIDsBuffer, rawArchetypeIDs); - SmallVector params; SmallVector requirements; - SmallVector archetypes; - - // The GenericTypeParamDecls might be from a different module file. - // If so, we need to map the archetype IDs from the serialized - // all-archetypes list in this module file over to the corresponding - // archetypes from the original generic parameter decls, or else - // we'll end up constructing fresh archetypes that don't match the - // ones from the generic parameters. - - // We have to do this mapping before we might call getType on one of - // those archetypes, but after we've read all the generic parameters. - // Therefore we do it lazily. - bool haveMappedArchetypes = false; - auto mapArchetypes = [&] { - if (haveMappedArchetypes) return; - - GenericParamList::deriveAllArchetypes(params, archetypes); - assert(rawArchetypeIDs.size() == archetypes.size()); - for (unsigned index : indices(rawArchetypeIDs)) { - TypeID TID = rawArchetypeIDs[index]; - auto &typeOrOffset = Types[TID-1]; - if (typeOrOffset.isComplete()) { - // FIXME: this assertion is absolutely correct, but it's - // currently fouled up by the presence of archetypes in - // substitutions. Those *should* be irrelevant for all the - // cases where this is wrong, but... - - //assert(typeOrOffset.get().getPointer() == archetypes[index] && - // "already deserialized this archetype to a different type!"); - - // TODO: remove unsafeOverwrite when this hack goes away - typeOrOffset.unsafeOverwrite(archetypes[index]); - } else { - typeOrOffset = archetypes[index]; - } - } - - haveMappedArchetypes = true; - }; while (true) { lastRecordOffset.reset(); bool shouldContinue = true; - auto entry = Cursor.advance(AF_DontPopBlockAtEnd); + auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); if (entry.Kind != llvm::BitstreamEntry::Record) break; scratch.clear(); - unsigned recordID = Cursor.readRecord(entry.ID, scratch, + unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case GENERIC_PARAM: { - assert(!haveMappedArchetypes && - "generic parameters interleaved with requirements?"); DeclID paramDeclID; GenericParamLayout::readRecord(scratch, paramDeclID); auto genericParam = cast(getDecl(paramDeclID, DC)); @@ -760,8 +711,6 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, GenericRequirementLayout::readRecord(scratch, rawKind, rawTypeIDs[0], rawTypeIDs[1]); - mapArchetypes(); - switch (rawKind) { case GenericRequirementKind::Conformance: { auto subject = TypeLoc::withoutLoc(getType(rawTypeIDs[0])); @@ -817,13 +766,9 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, break; } - // Make sure we map the archetypes if we haven't yet. - mapArchetypes(); - auto paramList = GenericParamList::create(getContext(), SourceLoc(), params, SourceLoc(), requirements, SourceLoc()); - paramList->setAllArchetypes(getContext().AllocateCopy(archetypes)); paramList->setOuterParameters(outerParams ? outerParams : DC->getGenericParamsOfContext()); @@ -847,8 +792,7 @@ void ModuleFile::readGenericRequirements( break; scratch.clear(); - unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, - &blobData); + unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData); switch (recordID) { case GENERIC_REQUIREMENT: { uint8_t rawKind; @@ -906,6 +850,78 @@ void ModuleFile::readGenericRequirements( } } +GenericEnvironment *ModuleFile::readGenericEnvironment( + SmallVectorImpl ¶mTypes, + llvm::BitstreamCursor &Cursor) { + using namespace decls_block; + + BCOffsetRAII lastRecordOffset(Cursor); + SmallVector scratch; + StringRef blobData; + + TypeSubstitutionMap interfaceToArchetypeMap; + + while (true) { + lastRecordOffset.reset(); + bool shouldContinue = true; + + auto entry = Cursor.advance(AF_DontPopBlockAtEnd); + if (entry.Kind != llvm::BitstreamEntry::Record) + break; + + scratch.clear(); + unsigned recordID = Cursor.readRecord(entry.ID, scratch, &blobData); + switch (recordID) { + case GENERIC_ENVIRONMENT: { + uint64_t rawTypeIDs[2]; + GenericEnvironmentLayout::readRecord(scratch, + rawTypeIDs[0], rawTypeIDs[1]); + + auto paramTy = getType(rawTypeIDs[0])->castTo(); + auto contextTy = getType(rawTypeIDs[1]); + + auto result = interfaceToArchetypeMap.insert( + std::make_pair(paramTy, contextTy)); + + assert(result.second); + paramTypes.push_back(paramTy); + break; + } + default: + // This record is not part of the GenericEnvironment. + shouldContinue = false; + break; + } + + if (!shouldContinue) + break; + } + + if (interfaceToArchetypeMap.empty()) + return nullptr; + + return GenericEnvironment::get(getContext(), interfaceToArchetypeMap); +} + +std::pair +ModuleFile::maybeReadGenericSignature() { + SmallVector paramTypes; + + // Read the generic environment. + auto env = readGenericEnvironment(paramTypes, DeclTypeCursor); + + if (env == nullptr) + return std::make_pair(nullptr, nullptr); + + // Read the generic requirements. + SmallVector requirements; + readGenericRequirements(requirements); + + auto sig = GenericSignature::get(paramTypes, requirements); + + return std::make_pair(sig, env); +} + bool ModuleFile::readMembers(SmallVectorImpl &Members) { using namespace decls_block; @@ -2150,7 +2166,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; @@ -2160,18 +2176,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { declOrOffset = alias; if (genericParams) { - SmallVector paramTypes; - for (auto &genericParam : *genericParams) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } + GenericSignature *sig; + GenericEnvironment *env; - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + std::tie(sig, env) = maybeReadGenericSignature(); - auto sig = GenericSignature::get(paramTypes, requirements); + assert(sig && "generic typealias without signature"); alias->setGenericSignature(sig); + alias->setGenericEnvironment(env); } alias->computeType(); @@ -2294,7 +2306,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; @@ -2312,20 +2324,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (isImplicit) theStruct->setImplicit(); - if (genericParams) { - SmallVector paramTypes; - for (auto &genericParam : *theStruct->getGenericParams()) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + GenericSignature *sig; + GenericEnvironment *env; - auto sig = GenericSignature::get(paramTypes, requirements); - theStruct->setGenericSignature(sig); - } + std::tie(sig, env) = maybeReadGenericSignature(); + + theStruct->setGenericSignature(sig); + theStruct->setGenericEnvironment(env); theStruct->computeType(); @@ -2362,10 +2368,13 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(parent, DeclTypeCursor); + auto *genericParams = maybeReadGenericParams(parent); if (declOrOffset.isComplete()) return declOrOffset; + SmallVector genericParamTypes; + auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor); + // Resolve the name ids. SmallVector argNames; for (auto argNameID : argNameIDs) @@ -2408,6 +2417,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { ctor->setInterfaceType(interfaceType); } + ctor->setGenericEnvironment(genericEnv); + // Set the initializer interface type of the constructor. auto allocType = ctor->getInterfaceType(); auto selfTy = ctor->computeInterfaceSelfType(/*isInitializingCtor=*/true); @@ -2571,7 +2582,10 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { // Read generic params before reading the type, because the type may // reference generic parameters, and we want them to have a dummy // DeclContext for now. - GenericParamList *genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + GenericParamList *genericParams = maybeReadGenericParams(DC); + + SmallVector genericParamTypes; + auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor); auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling); if (!staticSpelling.hasValue()) { @@ -2640,6 +2654,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { fn->setInterfaceType(interfaceType); } + fn->setGenericEnvironment(genericEnv); + SmallVector paramLists; for (unsigned i = 0, e = numParamPatterns; i != e; ++i) paramLists.push_back(readParameterList()); @@ -2752,21 +2768,16 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { handleInherited(proto, rawProtocolAndInheritedIDs.slice(numProtocols)); - if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) { + if (auto genericParams = maybeReadGenericParams(DC)) proto->setGenericParams(genericParams); - SmallVector paramTypes; - for (auto &genericParam : *proto->getGenericParams()) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + GenericSignature *sig; + GenericEnvironment *env; - auto sig = GenericSignature::get(paramTypes, requirements); - proto->setGenericSignature(sig); - } + std::tie(sig, env) = maybeReadGenericSignature(); + + proto->setGenericSignature(sig); + proto->setGenericEnvironment(env); if (isImplicit) proto->setImplicit(); @@ -2919,7 +2930,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; @@ -2940,20 +2951,15 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { theClass->setSuperclass(getType(superclassID)); if (requiresStoredPropertyInits) theClass->setRequiresStoredPropertyInits(true); - if (genericParams) { - SmallVector paramTypes; - for (auto &genericParam : *theClass->getGenericParams()) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + GenericSignature *sig; + GenericEnvironment *env; + + std::tie(sig, env) = maybeReadGenericSignature(); + + theClass->setGenericSignature(sig); + theClass->setGenericEnvironment(env); - GenericSignature *sig = GenericSignature::get(paramTypes, requirements); - theClass->setGenericSignature(sig); - } theClass->computeType(); handleInherited(theClass, rawInheritedIDs); @@ -2987,7 +2993,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + auto genericParams = maybeReadGenericParams(DC); if (declOrOffset.isComplete()) return declOrOffset; @@ -3006,20 +3012,14 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (isImplicit) theEnum->setImplicit(); theEnum->setRawType(getType(rawTypeID)); - if (genericParams) { - SmallVector paramTypes; - for (auto &genericParam : *theEnum->getGenericParams()) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + GenericSignature *sig; + GenericEnvironment *env; - GenericSignature *sig = GenericSignature::get(paramTypes, requirements); - theEnum->setGenericSignature(sig); - } + std::tie(sig, env) = maybeReadGenericSignature(); + + theEnum->setGenericSignature(sig); + theEnum->setGenericEnvironment(env); theEnum->computeType(); @@ -3198,28 +3198,16 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { extension->setCheckedInheritanceClause(); // Generic parameters. - GenericParamList *genericParams = maybeReadGenericParams(DC, - DeclTypeCursor); + GenericParamList *genericParams = maybeReadGenericParams(DC); extension->setGenericParams(genericParams); - // Conjure up a generic signature from the generic parameters and - // requirements. - if (genericParams) { - SmallVector paramTypes; - for (auto &genericParam : *genericParams) { - paramTypes.push_back(genericParam->getDeclaredType() - ->castTo()); - } + GenericSignature *sig; + GenericEnvironment *env; - // Read the generic requirements. - SmallVector requirements; - readGenericRequirements(requirements); + std::tie(sig, env) = maybeReadGenericSignature(); - if (!paramTypes.empty()) { - GenericSignature *sig = GenericSignature::get(paramTypes, requirements); - extension->setGenericSignature(sig); - } - } + extension->setGenericSignature(sig); + extension->setGenericEnvironment(env); extension->setMemberLoader(this, DeclTypeCursor.GetCurrentBitNo()); skipRecord(DeclTypeCursor, decls_block::MEMBERS); @@ -3266,6 +3254,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { dtor->setGenericSignature(genericFnType->getGenericSignature()); dtor->setInterfaceType(interfaceType); + dtor->setGenericEnvironment(DC->getGenericEnvironmentOfContext()); + if (isImplicit) dtor->setImplicit(); @@ -3846,7 +3836,7 @@ Type ModuleFile::getType(TypeID TID) { rawRep, throws); GenericParamList *paramList = - maybeGetOrReadGenericParams(genericContextID, FileContext, DeclTypeCursor); + maybeGetOrReadGenericParams(genericContextID, FileContext); assert(paramList && "missing generic params for polymorphic function"); auto rep = getActualFunctionTypeRepresentation(rawRep); diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 64fcf9b593e97..31a3bbfeac30c 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -490,34 +490,18 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, fn->addSpecializeAttr(SILSpecializeAttr::create(SILMod, Substitutions)); } - GenericParamList *contextParams = nullptr; + GenericEnvironment *genericEnv = nullptr; if (!declarationOnly) { - // We need to construct a linked list of GenericParamList. The outermost - // list appears first in the module file. Force the declaration's context to - // be the current module, not the original module associated with this - // module file. A generic param decl at module scope cannot refer to another - // module because we would have no way lookup the original module when - // serializing a copy of the function. This comes up with generic - // reabstraction thunks which have shared linkage. - DeclContext *outerParamContext = SILMod.getSwiftModule(); - while (true) { - // Params' OuterParameters will point to contextParams. - auto *Params = MF->maybeReadGenericParams(outerParamContext, - SILCursor, contextParams); - if (!Params) - break; - // contextParams will point to the last deserialized list, which is the - // innermost one. - contextParams = Params; - } + SmallVector genericParamTypes; + genericEnv = MF->readGenericEnvironment(genericParamTypes, SILCursor); } // If the next entry is the end of the block, then this function has // no contents. entry = SILCursor.advance(AF_DontPopBlockAtEnd); bool isEmptyFunction = (entry.Kind == llvm::BitstreamEntry::EndBlock); - assert((!isEmptyFunction || !contextParams) && - "context params without body?!"); + assert((!isEmptyFunction || !genericEnv) && + "generic environment without body?!"); // Remember this in our cache in case it's a recursive function. // Increase the reference count to keep it alive. @@ -536,10 +520,10 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID, NumDeserializedFunc++; - assert(!(fn->getContextGenericParams() && !fn->empty()) + assert(!(fn->getGenericEnvironment() && !fn->empty()) && "function already has context generic params?!"); - if (contextParams) - fn->setContextGenericParams(contextParams); + if (genericEnv) + fn->setGenericEnvironment(genericEnv); scratch.clear(); kind = SILCursor.readRecord(entry.ID, scratch); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index f67b222ab263c..842116a58fd64 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -16,6 +16,7 @@ #include "swift/AST/ASTWalker.h" #include "swift/AST/DiagnosticsCommon.h" #include "swift/AST/ForeignErrorConvention.h" +#include "swift/AST/GenericEnvironment.h" #include "swift/AST/LinkLibrary.h" #include "swift/AST/Mangle.h" #include "swift/AST/RawComment.h" @@ -527,6 +528,8 @@ void Serializer::writeBlockInfoBlock() { decls_block::GENERIC_REQUIREMENT); BLOCK_RECORD_WITH_NAMESPACE(sil_block, decls_block::LAST_GENERIC_REQUIREMENT); + BLOCK_RECORD_WITH_NAMESPACE(sil_block, + decls_block::GENERIC_ENVIRONMENT); BLOCK(SIL_INDEX_BLOCK); BLOCK_RECORD(sil_index_block, SIL_FUNC_NAMES); @@ -931,7 +934,7 @@ static uint8_t getRawStableRequirementKind(RequirementKind kind) { #undef CASE } -void Serializer::writeRequirements(ArrayRef requirements) { +void Serializer::writeGenericRequirements(ArrayRef requirements) { using namespace decls_block; if (requirements.empty()) @@ -948,29 +951,23 @@ void Serializer::writeRequirements(ArrayRef requirements) { } } -bool Serializer::writeGenericParams(const GenericParamList *genericParams, - const std::array &abbrCodes) { +bool Serializer::writeGenericParams(const GenericParamList *genericParams) { using namespace decls_block; // Don't write anything if there are no generic params. if (!genericParams) return true; - SmallVector archetypeIDs; - for (auto archetype : genericParams->getAllArchetypes()) - archetypeIDs.push_back(addTypeRef(archetype)); + unsigned abbrCode = DeclTypeAbbrCodes[GenericParamListLayout::Code]; + GenericParamListLayout::emitRecord(Out, ScratchRecord, abbrCode); - unsigned abbrCode = abbrCodes[GenericParamListLayout::Code]; - GenericParamListLayout::emitRecord(Out, ScratchRecord, abbrCode, - archetypeIDs); - - abbrCode = abbrCodes[GenericParamLayout::Code]; + abbrCode = DeclTypeAbbrCodes[GenericParamLayout::Code]; for (auto next : genericParams->getParams()) { GenericParamLayout::emitRecord(Out, ScratchRecord, abbrCode, addDeclRef(next)); } - abbrCode = abbrCodes[GenericRequirementLayout::Code]; + abbrCode = DeclTypeAbbrCodes[GenericRequirementLayout::Code]; SmallString<64> ReqStr; for (auto next : genericParams->getRequirements()) { ReqStr.clear(); @@ -996,12 +993,37 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams, } } - abbrCode = abbrCodes[LastGenericRequirementLayout::Code]; + abbrCode = DeclTypeAbbrCodes[LastGenericRequirementLayout::Code]; uint8_t dummy = 0; LastGenericRequirementLayout::emitRecord(Out, ScratchRecord, abbrCode, dummy); return true; } +void Serializer::writeGenericEnvironment(GenericSignature *sig, + GenericEnvironment *env, + const std::array &abbrCodes) { + using namespace decls_block; + + if (env == nullptr) + return; + + auto &map = env->getInterfaceToArchetypeMap(); + + auto envAbbrCode = abbrCodes[GenericEnvironmentLayout::Code]; + + // Iterate over the signature's generic parameters, for stable + // iteration order. + for (auto *paramTy : sig->getGenericParams()) { + auto found = map.find(paramTy->getCanonicalType().getPointer()); + assert(found != map.end() && "missing generic parameter"); + auto contextTy = found->second; + GenericEnvironmentLayout::emitRecord( + Out, ScratchRecord, envAbbrCode, + addTypeRef(paramTy), + addTypeRef(contextTy)); + } +} + void Serializer::writeNormalConformance( const NormalProtocolConformance *conformance) { using namespace decls_block; @@ -1363,7 +1385,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) { genericParams); if (genericSig) { - writeRequirements(genericSig->getRequirements()); + writeGenericRequirements(genericSig->getRequirements()); } break; } @@ -2063,8 +2085,11 @@ void Serializer::writeDecl(const Decl *D) { isa(baseNominal); } - writeGenericParams(extension->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(extension->getGenericRequirements()); + writeGenericParams(extension->getGenericParams()); + writeGenericEnvironment(extension->getGenericSignature(), + extension->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(extension->getGenericRequirements()); writeMembers(extension->getMembers(), isClassExtension); writeConformances(conformances, DeclTypeAbbrCodes); @@ -2184,8 +2209,11 @@ void Serializer::writeDecl(const Decl *D) { addTypeRef(typeAlias->getInterfaceType()), typeAlias->isImplicit(), rawAccessLevel); - writeGenericParams(typeAlias->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(typeAlias->getGenericRequirements()); + writeGenericParams(typeAlias->getGenericParams()); + writeGenericEnvironment(typeAlias->getGenericSignature(), + typeAlias->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(typeAlias->getGenericRequirements()); break; } @@ -2260,8 +2288,11 @@ void Serializer::writeDecl(const Decl *D) { inheritedTypes); - writeGenericParams(theStruct->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theStruct->getGenericRequirements()); + writeGenericParams(theStruct->getGenericParams()); + writeGenericEnvironment(theStruct->getGenericSignature(), + theStruct->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theStruct->getGenericRequirements()); writeMembers(theStruct->getMembers(), false); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2294,8 +2325,11 @@ void Serializer::writeDecl(const Decl *D) { conformances.size(), inheritedTypes); - writeGenericParams(theEnum->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theEnum->getGenericRequirements()); + writeGenericParams(theEnum->getGenericParams()); + writeGenericEnvironment(theEnum->getGenericSignature(), + theEnum->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theEnum->getGenericRequirements()); writeMembers(theEnum->getMembers(), false); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2331,8 +2365,11 @@ void Serializer::writeDecl(const Decl *D) { conformances.size(), inheritedTypes); - writeGenericParams(theClass->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theClass->getGenericRequirements()); + writeGenericParams(theClass->getGenericParams()); + writeGenericEnvironment(theClass->getGenericSignature(), + theClass->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theClass->getGenericRequirements()); writeMembers(theClass->getMembers(), true); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2367,8 +2404,11 @@ void Serializer::writeDecl(const Decl *D) { numProtocols, protocolsAndInherited); - writeGenericParams(proto->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(proto->getGenericRequirements()); + writeGenericParams(proto->getGenericParams()); + writeGenericEnvironment(proto->getGenericSignature(), + proto->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(proto->getGenericRequirements()); writeMembers(proto->getMembers(), true); writeDefaultWitnessTable(proto, DeclTypeAbbrCodes); break; @@ -2468,7 +2508,10 @@ void Serializer::writeDecl(const Decl *D) { rawAccessLevel, nameComponents); - writeGenericParams(fn->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(fn->getGenericParams()); + writeGenericEnvironment(fn->getGenericSignature(), + fn->getGenericEnvironment(), + DeclTypeAbbrCodes); // Write the body parameters. for (auto pattern : fn->getParameterLists()) @@ -2585,7 +2628,11 @@ void Serializer::writeDecl(const Decl *D) { rawAccessLevel, nameComponents); - writeGenericParams(ctor->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(ctor->getGenericParams()); + writeGenericEnvironment(ctor->getGenericSignature(), + ctor->getGenericEnvironment(), + DeclTypeAbbrCodes); + assert(ctor->getParameterLists().size() == 2); // Why is this writing out the param list for self? for (auto paramList : ctor->getParameterLists()) @@ -2961,7 +3008,7 @@ void Serializer::writeType(Type ty) { getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()), fnTy->throws()); if (!genericContext) - writeGenericParams(&fnTy->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(&fnTy->getGenericParams()); break; } @@ -2979,7 +3026,7 @@ void Serializer::writeType(Type ty) { genericParams); // Write requirements. - writeRequirements(fnTy->getRequirements()); + writeGenericRequirements(fnTy->getRequirements()); break; } @@ -3045,9 +3092,7 @@ void Serializer::writeType(Type ty) { fnTy->getNumAllResults(), variableData); if (sig) - writeRequirements(sig->getRequirements()); - else - writeRequirements({}); + writeGenericRequirements(sig->getRequirements()); break; } @@ -3243,6 +3288,7 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); + registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 6b5e05c951170..7f4ae2cbb78dd 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -241,8 +241,11 @@ class Serializer { /// Writes the given pattern, recursively. void writePattern(const Pattern *pattern); + /// Writes a generic parameter list. + bool writeGenericParams(const GenericParamList *genericParams); + /// Writes a set of generic requirements. - void writeRequirements(ArrayRef requirements); + void writeGenericRequirements(ArrayRef requirements); /// Writes a list of protocol conformances. void writeConformances(ArrayRef conformances, @@ -411,9 +414,10 @@ class Serializer { void writeConformance(ProtocolConformance *conformance, const std::array &abbrCodes); - /// Writes a generic parameter list. - bool writeGenericParams(const GenericParamList *genericParams, - const std::array &abbrCodes); + /// Writes a generic environment. + void writeGenericEnvironment(GenericSignature *sig, + GenericEnvironment *env, + const std::array &abbrCodes); }; } // end namespace serialization diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 90ec7f4a28dc5..d48390259ce50 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -374,15 +374,9 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { // Write the body's context archetypes, unless we don't actually have a body. if (!F.isExternalDeclaration()) { - if (auto gp = F.getContextGenericParams()) { - // To help deserializing the context generic params, we serialize the - // outer-most list first. In most cases, we do not have decls associated - // with these parameter lists, so serialize the lists directly. - std::vector paramLists; - for (; gp; gp = gp->getOuterParameters()) - paramLists.push_back(gp); - for (unsigned i = 0, e = paramLists.size(); i < e; i++) - S.writeGenericParams(paramLists.rbegin()[i], SILAbbrCodes); + if (auto genericEnv = F.getGenericEnvironment()) { + auto genericSig = F.getLoweredFunctionType()->getGenericSignature(); + S.writeGenericEnvironment(genericSig, genericEnv, SILAbbrCodes); } } @@ -1850,10 +1844,8 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) { registerSILAbbr(); registerSILAbbr(); registerSILAbbr(); - registerSILAbbr(); - registerSILAbbr(); registerSILAbbr(); - registerSILAbbr(); + registerSILAbbr(); for (const SILGlobalVariable &g : SILMod->getSILGlobals()) writeSILGlobalVar(g); diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift index cff0d5e50bb00..34f18fc08ae4e 100644 --- a/test/SILGen/witnesses.swift +++ b/test/SILGen/witnesses.swift @@ -426,14 +426,14 @@ protocol GenericParameterNameCollisionProtocol { struct GenericParameterNameCollision : GenericParameterNameCollisionProtocol { - // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}foo{{.*}} : $@convention(witness_method) (@in T, @in_guaranteed GenericParameterNameCollision) -> () { - // CHECK: bb0(%0 : $*T, %1 : $*GenericParameterNameCollision): - // CHECK: apply {{%.*}} + // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}foo{{.*}} : $@convention(witness_method) (@in T1, @in_guaranteed GenericParameterNameCollision) -> () { + // CHECK: bb0(%0 : $*T1, %1 : $*GenericParameterNameCollision): + // CHECK: apply {{%.*}} func foo(_ x: U) {} - // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}bar{{.*}} : $@convention(witness_method) (@owned @callee_owned (@in T) -> @out T1.Assoc, @in_guaranteed GenericParameterNameCollision) -> () { - // CHECK: bb0(%0 : $@callee_owned (@in T) -> @out T1.Assoc, %1 : $*GenericParameterNameCollision): - // CHECK: apply {{%.*}} + // CHECK-LABEL: sil hidden [transparent] [thunk] @_TTW{{.*}}GenericParameterNameCollision{{.*}}GenericParameterNameCollisionProtocol{{.*}}bar{{.*}} : $@convention(witness_method) (@owned @callee_owned (@in T1) -> @out T.Assoc, @in_guaranteed GenericParameterNameCollision) -> () { + // CHECK: bb0(%0 : $@callee_owned (@in T1) -> @out T.Assoc, %1 : $*GenericParameterNameCollision): + // CHECK: apply {{%.*}} func bar(_ x: (V) -> T.Assoc) {} } diff --git a/utils/resolve-crashes.py b/utils/resolve-crashes.py index 1091ee81533fa..5935e3dcfb8e5 100755 --- a/utils/resolve-crashes.py +++ b/utils/resolve-crashes.py @@ -16,7 +16,7 @@ def execute_cmd(cmd): # The regular expression we use to match compiler-crasher lines. regex = re.compile( '.*Swift(.*) :: ' - '(compiler_crashers|compiler_crashers_2|IDE/crashers)/(.*\.swift).*') + '(compiler_crashers|compiler_crashers_2|IDE/crashers|SIL/crashers)/(.*\.swift|.*\.sil).*') # Take the output of lit as standard input. for line in sys.stdin: diff --git a/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil b/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil deleted file mode 100644 index ab7468ac86be7..0000000000000 --- a/validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil +++ /dev/null @@ -1,3 +0,0 @@ -// RUN: not --crash %target-sil-opt %s -// REQUIRES: asserts -protocol l{func t-> ()->( \ No newline at end of file diff --git a/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil b/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil deleted file mode 100644 index 5592b426ddfbd..0000000000000 --- a/validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil +++ /dev/null @@ -1,3 +0,0 @@ -// RUN: not --crash %target-sil-opt %s -// REQUIRES: asserts -sil_global@d:$(<τ>()->( \ No newline at end of file diff --git a/validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil b/validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil similarity index 56% rename from validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil rename to validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil index 1f6eaa678c87b..80c766efdd152 100644 --- a/validation-test/SIL/crashers/008-swift-genericparamlist-getasgenericsignatureelements.sil +++ b/validation-test/SIL/crashers_fixed/008-swift-genericparamlist-getasgenericsignatureelements.sil @@ -1,3 +1,3 @@ -// RUN: not --crash %target-sil-opt %s +// RUN: not %target-sil-opt %s // REQUIRES: asserts sil@__:$<__ where τ:k>()->( diff --git a/validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil b/validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil similarity index 54% rename from validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil rename to validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil index bed95c5b2d932..a04f13806b2d4 100644 --- a/validation-test/SIL/crashers/021-swift-typechecker-typecheckdecl.sil +++ b/validation-test/SIL/crashers_fixed/021-swift-typechecker-typecheckdecl.sil @@ -1,3 +1,3 @@ -// RUN: not --crash %target-sil-opt %s +// RUN: not %target-sil-opt %s // REQUIRES: asserts protocol P{var e:()->( diff --git a/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil b/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil new file mode 100644 index 0000000000000..16aa0fb227cde --- /dev/null +++ b/validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil @@ -0,0 +1,3 @@ +// RUN: not %target-sil-opt %s +// REQUIRES: asserts +protocol l{func t-> ()->( diff --git a/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil b/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil new file mode 100644 index 0000000000000..e9af348b2e2c1 --- /dev/null +++ b/validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil @@ -0,0 +1,3 @@ +// RUN: not %target-sil-opt %s +// REQUIRES: asserts +sil_global@d:$(<τ>()->( diff --git a/validation-test/compiler_crashers/28369-swift-decl-walk.swift b/validation-test/compiler_crashers/28369-swift-decl-walk.swift index 59d40a47f5838..10fbf9f683ba7 100644 --- a/validation-test/compiler_crashers/28369-swift-decl-walk.swift +++ b/validation-test/compiler_crashers/28369-swift-decl-walk.swift @@ -8,6 +8,7 @@ // Credits: https://twitter.com/kiliankoe/status/752090953977036800 // RUN: not --crash %target-swift-frontend %s -parse +// XFAIL: * protocol P { } struct A {