From 1c1ab0b83a9641e7ef1141d34338ac754b7a87ce Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 24 Aug 2016 16:26:26 -0700 Subject: [PATCH 01/13] AST: Introduce new GenericEnvironment class A GenericEnvironment stores the mapping between GenericTypeParamTypes and context archetypes (or eventually, concrete types, once we allow extensions to constrain a generic parameter to a concrete type). The goals here are two-fold: - Eliminate the GenericTypeParamDecl::getArchetype() method, and always use mapTypeIntoContext() instead - Replace SILFunction::ContextGenericParams with a GenericEnvironment This patch adds the new data type as well as serializer and AST verifier support. but nothing else uses it yet. Note that GenericSignature::get() now asserts if there are no generic parameters, instead of returning null. This requires a few tweaks here and there. --- include/swift/AST/ArchetypeBuilder.h | 10 +- include/swift/AST/Decl.h | 53 ++++- include/swift/AST/DeclContext.h | 16 +- include/swift/AST/GenericEnvironment.h | 64 ++++++ .../Serialization/DeclTypeRecordNodes.def | 1 + include/swift/Serialization/ModuleFile.h | 18 ++ include/swift/Serialization/ModuleFormat.h | 20 +- lib/AST/ASTContext.cpp | 10 +- lib/AST/ASTVerifier.cpp | 44 +++- lib/AST/ArchetypeBuilder.cpp | 23 ++ lib/AST/Builtins.cpp | 32 ++- lib/AST/CMakeLists.txt | 1 + lib/AST/Decl.cpp | 10 - lib/AST/DeclContext.cpp | 41 ++++ lib/AST/GenericEnvironment.cpp | 66 ++++++ lib/AST/GenericSignature.cpp | 2 + lib/AST/Type.cpp | 7 +- lib/ClangImporter/ImportDecl.cpp | 84 ++++++-- lib/Sema/CodeSynthesis.cpp | 4 + .../DerivedConformanceEquatableHashable.cpp | 2 + .../DerivedConformanceRawRepresentable.cpp | 1 + lib/Sema/DerivedConformances.cpp | 2 + lib/Sema/TypeCheckDecl.cpp | 85 +++++--- lib/Sema/TypeCheckGeneric.cpp | 56 +++-- lib/Sema/TypeChecker.h | 9 +- lib/Serialization/Deserialization.cpp | 199 +++++++++++------- lib/Serialization/Serialization.cpp | 76 +++++-- lib/Serialization/Serialization.h | 7 +- 28 files changed, 746 insertions(+), 197 deletions(-) create mode 100644 include/swift/AST/GenericEnvironment.h create mode 100644 lib/AST/GenericEnvironment.cpp diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 78e8c15882018..c3f3da25c43e6 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 diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 964a2dc927eea..39310953a2e25 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; @@ -1472,6 +1473,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 +1562,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 +2325,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 +2349,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 +2383,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 +4610,7 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext { GenericParamList *GenericParams; GenericSignature *GenericSig; + GenericEnvironment *GenericEnv; CaptureInfo Captures; @@ -4589,7 +4627,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 +4654,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..e420949081ce6 --- /dev/null +++ b/include/swift/AST/GenericEnvironment.h @@ -0,0 +1,64 @@ +//===--- 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; +}; + +} // end namespace swift + +#endif // SWIFT_AST_GENERIC_ENVIRONMENT_H + 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..ef28c3d293586 100644 --- a/include/swift/Serialization/ModuleFile.h +++ b/include/swift/Serialization/ModuleFile.h @@ -432,6 +432,24 @@ class ModuleFile : public LazyMemberLoader { /// 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. diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 2585dde4ef5a6..5845318e66ce6 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 = 262; // Last change: serialize GenericEnvironment using DeclID = PointerEmbeddedInt; using DeclIDField = BCFixed<31>; @@ -1092,6 +1092,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/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/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index f83926c885235..f524a5de0abe6 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()); @@ -2326,6 +2364,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. diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index d468d85c0dadb..3107e399f2bb2 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" @@ -2303,3 +2304,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..d42c5020d19fe 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); @@ -469,6 +474,8 @@ namespace { SmallVector GenericTypeParams; SmallVector Archetypes; + TypeSubstitutionMap InterfaceToArchetypeMap; + SmallVector InterfaceParams; SmallVector BodyParams; @@ -480,6 +487,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 +510,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..18f2d972d82c5 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -818,11 +818,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 +2211,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..5b83b7c0d1fdc --- /dev/null +++ b/lib/AST/GenericEnvironment.cpp @@ -0,0 +1,66 @@ +//===--- 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; +} 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/Type.cpp b/lib/AST/Type.cpp index e10a0be1d7380..bda89e8c3728f 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3489,8 +3489,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 +3506,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..9172239300137 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( @@ -5169,7 +5183,10 @@ namespace { 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 +5524,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) { @@ -5687,6 +5707,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 +5847,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; @@ -6976,8 +7007,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/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 08b0253bcff65..d51cece9c54cf 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1303,6 +1303,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 +1322,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 +1400,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. @@ -2132,6 +2135,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..b45548cb54cba 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. @@ -724,7 +734,7 @@ GenericSignature *TypeChecker::handleSILGenericParams( ArchetypeBuilder builder(*DC->getParentModule(), Diags); checkGenericParamList(&builder, genericParams, parentSig); - finalizeGenericParamList(builder, genericParams, DC); + finalizeGenericParamList(builder, genericParams, genericSig, DC); parentSig = genericSig; } @@ -4698,7 +4708,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 +4732,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()) { 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. @@ -6384,7 +6399,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 +6415,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()) { 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()); } } @@ -6554,8 +6575,11 @@ class DeclChecker : public DeclVisitor { Type SelfTy = configureImplicitSelf(TC, DD); - if (DD->getDeclContext()->isGenericContext()) + if (DD->getDeclContext()->isGenericContext()) { TC.validateGenericFuncSignature(DD); + DD->setGenericEnvironment( + DD->getDeclContext()->getGenericEnvironmentOfContext()); + } if (semaFuncParamPatterns(DD)) { DD->overwriteType(ErrorType::get(TC.Context)); @@ -7328,8 +7352,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 +7375,7 @@ static Type checkExtensionGenericParams( tc, ext, parentType, nominal->getGenericParams() ? genericParams->getOuterParameters() - : genericParams, - sig); + : genericParams); if (!newParentType) return Type(); } @@ -7396,9 +7418,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 +7435,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 +7504,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 +7538,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 +7558,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..f06472c3446b3 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -471,33 +471,39 @@ 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) + if (!DC->isInnermostContextGeneric()) return; - DeclContext *DC = VD->getDeclContext(); - ArchetypeBuilder builder = createArchetypeBuilder(DC->getParentModule()); + GenericParamList *genericParams = DC->getGenericParamsOfContext(); + GenericSignature *genericSig = DC->getGenericSignatureOfContext(); + + // Build new archetypes without any generic requirements. + DeclContext *parentDC = DC->getParent(); + auto builder = createArchetypeBuilder(parentDC->getParentModule()); - if (auto sig = DC->getGenericSignatureOfContext()) - builder.addGenericSignature(sig, true); + auto parentSig = parentDC->getGenericSignatureOfContext(); + + 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 +546,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 +795,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,6 +810,11 @@ 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); @@ -859,6 +872,8 @@ void TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, break; } } + + return genericEnv; } /// Revert the dependent types within the given generic parameter list. @@ -903,13 +918,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 +935,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/TypeChecker.h b/lib/Sema/TypeChecker.h index 0694cb74c3dd5..fd3f833087a81 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -996,7 +996,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 +1044,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); + GenericEnvironmet *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..d8992dbccb9ae 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" @@ -847,8 +848,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 +906,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; @@ -2160,18 +2232,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(); @@ -2312,20 +2380,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 +2424,13 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { if (declOrOffset.isComplete()) return declOrOffset; - auto genericParams = maybeReadGenericParams(parent, DeclTypeCursor); + auto *genericParams = maybeReadGenericParams(parent, DeclTypeCursor); if (declOrOffset.isComplete()) return declOrOffset; + SmallVector genericParamTypes; + auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor); + // Resolve the name ids. SmallVector argNames; for (auto argNameID : argNameIDs) @@ -2408,6 +2473,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); @@ -2573,6 +2640,9 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { // DeclContext for now. GenericParamList *genericParams = maybeReadGenericParams(DC, DeclTypeCursor); + SmallVector genericParamTypes; + auto *genericEnv = readGenericEnvironment(genericParamTypes, DeclTypeCursor); + auto staticSpelling = getActualStaticSpellingKind(rawStaticSpelling); if (!staticSpelling.hasValue()) { error(); @@ -2640,6 +2710,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 +2824,16 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { handleInherited(proto, rawProtocolAndInheritedIDs.slice(numProtocols)); - if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) { + if (auto genericParams = maybeReadGenericParams(DC, DeclTypeCursor)) 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(); @@ -2940,20 +3007,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); @@ -3006,20 +3068,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(); @@ -3202,24 +3258,13 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { DeclTypeCursor); 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 +3311,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { dtor->setGenericSignature(genericFnType->getGenericSignature()); dtor->setInterfaceType(interfaceType); + dtor->setGenericEnvironment(DC->getGenericEnvironmentOfContext()); + if (isImplicit) dtor->setImplicit(); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index f67b222ab263c..65e354d082d59 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()) @@ -1002,6 +1005,31 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams, 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 +1391,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) { genericParams); if (genericSig) { - writeRequirements(genericSig->getRequirements()); + writeGenericRequirements(genericSig->getRequirements()); } break; } @@ -2064,7 +2092,10 @@ void Serializer::writeDecl(const Decl *D) { } writeGenericParams(extension->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(extension->getGenericRequirements()); + writeGenericEnvironment(extension->getGenericSignature(), + extension->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(extension->getGenericRequirements()); writeMembers(extension->getMembers(), isClassExtension); writeConformances(conformances, DeclTypeAbbrCodes); @@ -2185,7 +2216,10 @@ void Serializer::writeDecl(const Decl *D) { typeAlias->isImplicit(), rawAccessLevel); writeGenericParams(typeAlias->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(typeAlias->getGenericRequirements()); + writeGenericEnvironment(typeAlias->getGenericSignature(), + typeAlias->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(typeAlias->getGenericRequirements()); break; } @@ -2261,7 +2295,10 @@ void Serializer::writeDecl(const Decl *D) { writeGenericParams(theStruct->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theStruct->getGenericRequirements()); + writeGenericEnvironment(theStruct->getGenericSignature(), + theStruct->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theStruct->getGenericRequirements()); writeMembers(theStruct->getMembers(), false); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2295,7 +2332,10 @@ void Serializer::writeDecl(const Decl *D) { inheritedTypes); writeGenericParams(theEnum->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theEnum->getGenericRequirements()); + writeGenericEnvironment(theEnum->getGenericSignature(), + theEnum->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theEnum->getGenericRequirements()); writeMembers(theEnum->getMembers(), false); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2332,7 +2372,10 @@ void Serializer::writeDecl(const Decl *D) { inheritedTypes); writeGenericParams(theClass->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(theClass->getGenericRequirements()); + writeGenericEnvironment(theClass->getGenericSignature(), + theClass->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(theClass->getGenericRequirements()); writeMembers(theClass->getMembers(), true); writeConformances(conformances, DeclTypeAbbrCodes); break; @@ -2368,7 +2411,10 @@ void Serializer::writeDecl(const Decl *D) { protocolsAndInherited); writeGenericParams(proto->getGenericParams(), DeclTypeAbbrCodes); - writeRequirements(proto->getGenericRequirements()); + writeGenericEnvironment(proto->getGenericSignature(), + proto->getGenericEnvironment(), + DeclTypeAbbrCodes); + writeGenericRequirements(proto->getGenericRequirements()); writeMembers(proto->getMembers(), true); writeDefaultWitnessTable(proto, DeclTypeAbbrCodes); break; @@ -2469,6 +2515,9 @@ void Serializer::writeDecl(const Decl *D) { nameComponents); writeGenericParams(fn->getGenericParams(), DeclTypeAbbrCodes); + writeGenericEnvironment(fn->getGenericSignature(), + fn->getGenericEnvironment(), + DeclTypeAbbrCodes); // Write the body parameters. for (auto pattern : fn->getParameterLists()) @@ -2586,6 +2635,10 @@ void Serializer::writeDecl(const Decl *D) { nameComponents); writeGenericParams(ctor->getGenericParams(), DeclTypeAbbrCodes); + 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()) @@ -2979,7 +3032,7 @@ void Serializer::writeType(Type ty) { genericParams); // Write requirements. - writeRequirements(fnTy->getRequirements()); + writeGenericRequirements(fnTy->getRequirements()); break; } @@ -3045,9 +3098,7 @@ void Serializer::writeType(Type ty) { fnTy->getNumAllResults(), variableData); if (sig) - writeRequirements(sig->getRequirements()); - else - writeRequirements({}); + writeGenericRequirements(sig->getRequirements()); break; } @@ -3243,6 +3294,7 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); + registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 6b5e05c951170..cfa93c04b363f 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -242,7 +242,12 @@ class Serializer { void writePattern(const Pattern *pattern); /// Writes a set of generic requirements. - void writeRequirements(ArrayRef requirements); + void writeGenericRequirements(ArrayRef requirements); + + /// Writes generic environment. + void writeGenericEnvironment(GenericSignature *sig, + GenericEnvironment *env, + const std::array &abbrCodes); /// Writes a list of protocol conformances. void writeConformances(ArrayRef conformances, From b9b296b32a0edee862a89d256362ea197114a4cb Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 24 Aug 2016 22:03:32 -0700 Subject: [PATCH 02/13] AST: Use GenericEnvironment in ArchetypeBuilder::mapType{Into,OutOf}Context() When we call the DeclContext variants of these, use the DeclContext's GenericEnvironment instead of GenericParamList. Also, these functions would take a resolver argument, but we always passed in nullptr, so just remove it now. The old GenericParamList-based versions are still there since they're called directly from SIL. They will go away once SILFunction::ContextGenericParams is replaced with a GenericEnvironment. --- include/swift/AST/ArchetypeBuilder.h | 18 ++++++--- lib/AST/ArchetypeBuilder.cpp | 56 ++++++++++++++++++++-------- lib/IRGen/GenMeta.cpp | 4 +- lib/IRGen/GenProto.cpp | 2 +- lib/SILGen/SILGenBridging.cpp | 5 ++- 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index c3f3da25c43e6..5e1ee047a6449 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -329,18 +329,26 @@ class ArchetypeBuilder { 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, + GenericEnvironment *genericEnv, + Type type); + + /// Map an interface type to a contextual type. + static Type mapTypeIntoContext(ModuleDecl *M, + GenericParamList *genericParams, + Type type); + /// Map a contextual type to an interface type. static Type mapTypeOutOfContext(ModuleDecl *M, GenericParamList *genericParams, diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index 3107e399f2bb2..f69408952f94f 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -2011,17 +2011,49 @@ 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(ModuleDecl *M, + GenericEnvironment *env, + Type type) { + auto canType = type->getCanonicalType(); + assert(!canType->hasArchetype() && "already have a contextual type"); + if (!canType->hasTypeParameter()) + return type; + + assert(env && "dependent type in non-generic context"); + + return env->mapTypeIntoContext(M, type); +} + +Type +ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) { + return mapTypeOutOfContext(dc->getParentModule(), + dc->getGenericEnvironmentOfContext(), + 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(env && "dependent type in non-generic context"); + + return env->mapTypeOutOfContext(M, type); } Type ArchetypeBuilder::mapTypeIntoContext(Module *M, GenericParamList *genericParams, - Type type, - LazyResolver *resolver) { + Type type) { auto canType = type->getCanonicalType(); assert(!canType->hasArchetype() && "already have a contextual type"); if (!canType->hasTypeParameter()) @@ -2053,8 +2085,8 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M, // 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); + dependentMember->getBase()); + return dependentMember->substBaseType(M, base); } return type; @@ -2064,12 +2096,6 @@ Type ArchetypeBuilder::mapTypeIntoContext(Module *M, return type; } -Type -ArchetypeBuilder::mapTypeOutOfContext(const DeclContext *dc, Type type) { - GenericParamList *genericParams = dc->getGenericParamsOfContext(); - return mapTypeOutOfContext(dc->getParentModule(), genericParams, type); -} - Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, GenericParamList *genericParams, Type 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/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index ce9c2bf1c0c87..f70048610bfeb 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -1282,8 +1282,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, From ca0b5485841e1c6f48d2ed0e64baad98df7c8402 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 25 Aug 2016 22:42:33 -0700 Subject: [PATCH 03/13] SIL: Replace SILFunction::ContextGenericParams with a GenericEnvironment This patch is rather large, since it was hard to make this change incrementally, but most of the changes are mechanical. Now that we have a lighter-weight data structure in the AST for mapping interface types to archetypes and vice versa, use that in SIL instead of a GenericParamList. This means that when serializing a SILFunction body, we no longer need to serialize references to archetypes from other modules. Several methods used for forming substitutions can now be moved from GenericParamList to GenericEnvironment. Also, GenericParamList::cloneWithOuterParameters() and GenericParamList::getEmpty() can now go away, since they were only used when SILGen-ing witness thunks. Finally, when printing generic parameters with identical names, the SIL printer used to number them from highest depth to lowest, by walking generic parameter lists starting with the innermost one. Now, ambiguous generic parameters are numbered from lowest depth to highest, by walking the generic signature, which means test output in one of the SILGen tests has changed. --- include/swift/AST/Decl.h | 43 ------- include/swift/AST/GenericEnvironment.h | 13 ++ include/swift/AST/PrintOptions.h | 7 +- include/swift/AST/ProtocolConformance.h | 3 + include/swift/AST/Substitution.h | 5 +- include/swift/AST/TypeRepr.h | 4 +- include/swift/SIL/SILFunction.h | 22 ++-- include/swift/SIL/SILModule.h | 2 +- include/swift/SIL/TypeLowering.h | 25 ++-- include/swift/SIL/TypeSubstCloner.h | 8 +- include/swift/Serialization/ModuleFormat.h | 2 +- include/swift/Subsystems.h | 8 +- lib/AST/ASTPrinter.cpp | 24 ++-- lib/AST/Decl.cpp | 34 ----- lib/AST/GenericEnvironment.cpp | 39 ++++++ lib/AST/Module.cpp | 17 +-- lib/AST/ProtocolConformance.cpp | 35 ++++-- lib/AST/Substitution.cpp | 7 +- lib/AST/Type.cpp | 28 ----- lib/Parse/ParseSIL.cpp | 116 ++++++++++++------ lib/SIL/SILFunction.cpp | 22 ++-- lib/SIL/SILFunctionType.cpp | 10 +- lib/SIL/SILModule.cpp | 4 +- lib/SIL/SILPrinter.cpp | 32 ++--- lib/SIL/SILVerifier.cpp | 26 ++-- lib/SIL/TypeLowering.cpp | 47 +++---- lib/SILGen/SILGen.cpp | 3 +- lib/SILGen/SILGen.h | 2 +- lib/SILGen/SILGenBridging.cpp | 30 ++--- lib/SILGen/SILGenConstructor.cpp | 13 +- lib/SILGen/SILGenDecl.cpp | 43 ++++--- lib/SILGen/SILGenFunction.cpp | 5 +- lib/SILGen/SILGenLValue.cpp | 8 +- lib/SILGen/SILGenMaterializeForSet.cpp | 12 +- lib/SILGen/SILGenPoly.cpp | 17 +-- lib/SILGen/SILGenType.cpp | 2 +- lib/SILOptimizer/IPO/CapturePromotion.cpp | 5 +- lib/SILOptimizer/IPO/ClosureSpecializer.cpp | 2 +- .../Mandatory/MandatoryInlining.cpp | 3 +- .../Transforms/AllocBoxToStack.cpp | 2 +- lib/SILOptimizer/Utils/Generics.cpp | 9 +- lib/Sema/CodeSynthesis.cpp | 26 ++-- lib/Sema/TypeCheckDecl.cpp | 20 +-- lib/Sema/TypeCheckGeneric.cpp | 2 +- lib/Sema/TypeChecker.cpp | 7 +- lib/Sema/TypeChecker.h | 13 +- lib/Serialization/DeserializeSIL.cpp | 32 ++--- lib/Serialization/Serialization.h | 10 +- lib/Serialization/SerializeSIL.cpp | 13 +- test/SILGen/witnesses.swift | 12 +- 50 files changed, 423 insertions(+), 451 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 39310953a2e25..f373af38699c6 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1110,28 +1110,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}; } @@ -1149,12 +1127,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; } @@ -1271,27 +1243,12 @@ 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. /// diff --git a/include/swift/AST/GenericEnvironment.h b/include/swift/AST/GenericEnvironment.h index e420949081ce6..14592b4a4b6b1 100644 --- a/include/swift/AST/GenericEnvironment.h +++ b/include/swift/AST/GenericEnvironment.h @@ -56,6 +56,19 @@ class GenericEnvironment final { /// 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 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..d50d27ebb9e16 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -236,6 +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. + GenericEnvironment *getGenericEnvironment() const; /// Get the generic parameters open on the conforming type. /// FIXME: Retire in favor of getGenericSignature(). 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..814b6ef33aa47 100644 --- a/include/swift/AST/TypeRepr.h +++ b/include/swift/AST/TypeRepr.h @@ -378,7 +378,9 @@ 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) { } 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/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 5845318e66ce6..dde14535d7628 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 = 262; // Last change: serialize GenericEnvironment +const uint16_t VERSION_MINOR = 263; // Last change: remove SILFunction::ContextGenericParams using DeclID = PointerEmbeddedInt; using DeclIDField = BCFixed<31>; 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/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 2905219a765ce..e9f4636a7fb5a 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(); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 18f2d972d82c5..ee315ac99ffcc 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -536,40 +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, diff --git a/lib/AST/GenericEnvironment.cpp b/lib/AST/GenericEnvironment.cpp index 5b83b7c0d1fdc..e13b02c7c284d 100644 --- a/lib/AST/GenericEnvironment.cpp +++ b/lib/AST/GenericEnvironment.cpp @@ -64,3 +64,42 @@ Type GenericEnvironment::mapTypeIntoContext(ModuleDecl *M, Type type) const { 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/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..0fdd357ae6948 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,6 +181,24 @@ usesDefaultDefinition(AssociatedTypeDecl *requirement) const { CONFORMANCE_SUBCLASS_DISPATCH(usesDefaultDefinition, (requirement)) } +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()->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; + } +} + GenericParamList *ProtocolConformance::getGenericParams() const { switch (getKind()) { case ProtocolConformanceKind::Inherited: @@ -354,7 +373,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 +385,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 +542,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 bda89e8c3728f..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(); diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp index fa2bee07ce9ae..c9e4b2c852717 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,7 +873,8 @@ 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); } } @@ -888,9 +900,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 +928,7 @@ bool SILParser::parseSILType(SILType &Result, attrs.convention = "thin"; } return parseSILTypeWithoutQualifiers(Result, category, attrs, - GenericSig, GenericParams, + GenericSig, GenericEnv, GenericParams, IsFuncDecl); } @@ -1479,20 +1493,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 +1520,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 +1536,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 +1898,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 +1911,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 +2401,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 +2412,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 +2420,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 +2430,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,7 +2937,10 @@ 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); } } @@ -3615,6 +3642,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { UnresolvedValueName invokeName; SILType invokeTy; GenericSignature *invokeGenericSig; + GenericEnvironment *invokeGenericEnv; GenericParamList *invokeGenericParams; SILType blockType; @@ -3628,7 +3656,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 +3682,9 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { return true; } if (getApplySubstitutionsFromParsed(*this, - invokeGenericSig, invokeGenericParams, + invokeGenericSig, + invokeGenericEnv, parsedSubs, subs)) return true; } @@ -3702,10 +3731,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 +3746,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 +3990,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 +4023,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 +4373,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 +4387,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 +4436,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 +4509,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 +4947,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 f70048610bfeb..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; 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 d51cece9c54cf..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(), @@ -1442,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)); } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index b45548cb54cba..db84a014b9724 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -706,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); @@ -722,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, genericSig, 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 @@ -2505,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; diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index f06472c3446b3..7d9b96dfd53ac 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -475,7 +475,7 @@ GenericEnvironment * TypeChecker::markInvalidGenericSignature(DeclContext *DC) { // If there aren't any generic parameters at this level, we're done. if (!DC->isInnermostContextGeneric()) - return; + return nullptr; GenericParamList *genericParams = DC->getGenericParamsOfContext(); GenericSignature *genericSig = DC->getGenericSignatureOfContext(); 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 fd3f833087a81..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. /// @@ -1044,10 +1045,10 @@ class TypeChecker final : public LazyResolver { /// Finalize the given generic parameter list, assigning archetypes to /// the generic parameters. - GenericEnvironmet *finalizeGenericParamList(ArchetypeBuilder &builder, - GenericParamList *genericParams, - GenericSignature *genericSig, - DeclContext *dc); + GenericEnvironment *finalizeGenericParamList(ArchetypeBuilder &builder, + GenericParamList *genericParams, + GenericSignature *genericSig, + DeclContext *dc); /// Validate the signature of a generic type. /// 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.h b/lib/Serialization/Serialization.h index cfa93c04b363f..59e847e87bf44 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -244,11 +244,6 @@ class Serializer { /// Writes a set of generic requirements. void writeGenericRequirements(ArrayRef requirements); - /// Writes generic environment. - void writeGenericEnvironment(GenericSignature *sig, - GenericEnvironment *env, - const std::array &abbrCodes); - /// Writes a list of protocol conformances. void writeConformances(ArrayRef conformances, const std::array &abbrCodes); @@ -420,6 +415,11 @@ class Serializer { 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 } // end namespace swift diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 90ec7f4a28dc5..5f56e23e4089b 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); } } @@ -1854,6 +1848,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) { 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) {} } From e23cc458dd6690250b385aa0ae296397151e18ad Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 25 Aug 2016 22:51:05 -0700 Subject: [PATCH 04/13] AST: Nuke GenericParamList versions of ArchetypeBuilder::mapType{Into,OutOf}Context() The last remaining use was in the SIL parser. Plumb through a GenericEnvironment. The code here really could use additional cleanup... --- include/swift/AST/ArchetypeBuilder.h | 10 ---- include/swift/AST/TypeRepr.h | 9 +++- lib/AST/ArchetypeBuilder.cpp | 70 ---------------------------- lib/Parse/ParseSIL.cpp | 2 + lib/Sema/TypeCheckType.cpp | 14 +++--- 5 files changed, 17 insertions(+), 88 deletions(-) diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 5e1ee047a6449..43989b9353115 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -344,16 +344,6 @@ class ArchetypeBuilder { GenericEnvironment *genericEnv, Type type); - /// Map an interface type to a contextual type. - static Type mapTypeIntoContext(ModuleDecl *M, - GenericParamList *genericParams, - Type type); - - /// Map a contextual type to an interface type. - static Type mapTypeOutOfContext(ModuleDecl *M, - GenericParamList *genericParams, - Type type); - using SameTypeRequirement = std::pair>; diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h index 814b6ef33aa47..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; @@ -386,6 +387,7 @@ class FunctionTypeRepr : public TypeRepr { } GenericParamList *getGenericParams() const { return GenericParams; } + GenericEnvironment *getGenericEnvironment() const { return GenericEnv; } GenericSignature *getGenericSignature() const { return GenericSig; } void setGenericSignature(GenericSignature *genericSig) { @@ -393,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/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index f69408952f94f..9db1c79ff2a1d 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -2051,76 +2051,6 @@ ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, return env->mapTypeOutOfContext(M, type); } -Type ArchetypeBuilder::mapTypeIntoContext(Module *M, - GenericParamList *genericParams, - 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()); - return dependentMember->substBaseType(M, base); - } - - return type; - }); - - assert(!type->hasTypeParameter() && "not fully substituted"); - return type; -} - -Type ArchetypeBuilder::mapTypeOutOfContext(ModuleDecl *M, - GenericParamList *genericParams, - 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"); - - // 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; -} - void ArchetypeBuilder::addGenericSignature(GenericSignature *sig, bool adoptArchetypes, bool treatRequirementsAsExplicit) { diff --git a/lib/Parse/ParseSIL.cpp b/lib/Parse/ParseSIL.cpp index c9e4b2c852717..c8dc4a633fad6 100644 --- a/lib/Parse/ParseSIL.cpp +++ b/lib/Parse/ParseSIL.cpp @@ -876,6 +876,7 @@ bool SILParser::parseSILTypeWithoutQualifiers(SILType &Result, std::tie(GenericSig, GenericEnv) = handleSILGenericParams(P.Context, generics, &P.SF); fnType->setGenericSignature(GenericSig); + fnType->setGenericEnvironment(GenericEnv); } } @@ -2942,6 +2943,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) { std::tie(genericSig, genericEnv) = handleSILGenericParams(P.Context, generics, &P.SF); fnType->setGenericSignature(genericSig); + fnType->setGenericEnvironment(genericEnv); } } diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c9d409867f515..94e9f9fbbbfbb 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -2131,11 +2131,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 +2224,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); } From 4c45324b297560a6786e4314c846b15487a220f6 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 25 Aug 2016 22:54:41 -0700 Subject: [PATCH 05/13] AST: Nuke ProtocolConformance::getGenericParams() --- include/swift/AST/ProtocolConformance.h | 4 ---- lib/AST/ASTPrinter.cpp | 17 +++++------------ lib/AST/ProtocolConformance.cpp | 16 ---------------- 3 files changed, 5 insertions(+), 32 deletions(-) diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index d50d27ebb9e16..34e2b8759399c 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -239,10 +239,6 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance { /// Get the generic parameters open on the conforming type. GenericEnvironment *getGenericEnvironment() const; - - /// Get the generic parameters open on the conforming type. - /// FIXME: Retire in favor of getGenericSignature(). - GenericParamList *getGenericParams() const; /// Get the generic signature containing the parameters open on the conforming /// interface type. diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index e9f4636a7fb5a..88d53106b3722 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -4473,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/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 0fdd357ae6948..37555cf13e118 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -199,22 +199,6 @@ GenericEnvironment *ProtocolConformance::getGenericEnvironment() const { } } -GenericParamList *ProtocolConformance::getGenericParams() 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(); - - 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. - return nullptr; - } -} - GenericSignature *ProtocolConformance::getGenericSignature() const { switch (getKind()) { case ProtocolConformanceKind::Inherited: From 58ceb472fa6440f67e165d6d2da895249236cb44 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 26 Aug 2016 00:05:03 -0700 Subject: [PATCH 06/13] Serialization: Remove support for serializing GenericParamList from SIL Now that SILFunctions store a GenericEnvironment instead of a GenericParamList, we can remove some unused flexibility. --- include/swift/Serialization/ModuleFile.h | 18 ++++++------ lib/Serialization/Deserialization.cpp | 36 +++++++++++------------- lib/Serialization/Serialization.cpp | 29 +++++++++---------- lib/Serialization/Serialization.h | 7 ++--- lib/Serialization/SerializeSIL.cpp | 3 -- 5 files changed, 42 insertions(+), 51 deletions(-) diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h index ef28c3d293586..ba1ef5fa7340a 100644 --- a/include/swift/Serialization/ModuleFile.h +++ b/include/swift/Serialization/ModuleFile.h @@ -426,8 +426,14 @@ 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); @@ -709,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/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index d8992dbccb9ae..34942786a6995 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -634,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"); @@ -648,29 +647,29 @@ 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, rawArchetypeIDsBuffer, + &blobData); if (kind != GENERIC_PARAM_LIST) return nullptr; @@ -724,12 +723,12 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, 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: { @@ -2222,7 +2221,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; @@ -2362,7 +2361,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; @@ -2424,7 +2423,7 @@ 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; @@ -2638,7 +2637,7 @@ 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); @@ -2824,7 +2823,7 @@ 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); GenericSignature *sig; @@ -2986,7 +2985,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; @@ -3049,7 +3048,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; @@ -3254,8 +3253,7 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { extension->setCheckedInheritanceClause(); // Generic parameters. - GenericParamList *genericParams = maybeReadGenericParams(DC, - DeclTypeCursor); + GenericParamList *genericParams = maybeReadGenericParams(DC); extension->setGenericParams(genericParams); GenericSignature *sig; @@ -3893,7 +3891,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/Serialization.cpp b/lib/Serialization/Serialization.cpp index 65e354d082d59..0e4054b337940 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -951,8 +951,7 @@ void Serializer::writeGenericRequirements(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. @@ -963,17 +962,17 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams, for (auto archetype : genericParams->getAllArchetypes()) archetypeIDs.push_back(addTypeRef(archetype)); - unsigned abbrCode = abbrCodes[GenericParamListLayout::Code]; + unsigned abbrCode = DeclTypeAbbrCodes[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(); @@ -999,7 +998,7 @@ 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; @@ -2091,7 +2090,7 @@ void Serializer::writeDecl(const Decl *D) { isa(baseNominal); } - writeGenericParams(extension->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(extension->getGenericParams()); writeGenericEnvironment(extension->getGenericSignature(), extension->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2215,7 +2214,7 @@ void Serializer::writeDecl(const Decl *D) { addTypeRef(typeAlias->getInterfaceType()), typeAlias->isImplicit(), rawAccessLevel); - writeGenericParams(typeAlias->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(typeAlias->getGenericParams()); writeGenericEnvironment(typeAlias->getGenericSignature(), typeAlias->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2294,7 +2293,7 @@ void Serializer::writeDecl(const Decl *D) { inheritedTypes); - writeGenericParams(theStruct->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(theStruct->getGenericParams()); writeGenericEnvironment(theStruct->getGenericSignature(), theStruct->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2331,7 +2330,7 @@ void Serializer::writeDecl(const Decl *D) { conformances.size(), inheritedTypes); - writeGenericParams(theEnum->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(theEnum->getGenericParams()); writeGenericEnvironment(theEnum->getGenericSignature(), theEnum->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2371,7 +2370,7 @@ void Serializer::writeDecl(const Decl *D) { conformances.size(), inheritedTypes); - writeGenericParams(theClass->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(theClass->getGenericParams()); writeGenericEnvironment(theClass->getGenericSignature(), theClass->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2410,7 +2409,7 @@ void Serializer::writeDecl(const Decl *D) { numProtocols, protocolsAndInherited); - writeGenericParams(proto->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(proto->getGenericParams()); writeGenericEnvironment(proto->getGenericSignature(), proto->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2514,7 +2513,7 @@ void Serializer::writeDecl(const Decl *D) { rawAccessLevel, nameComponents); - writeGenericParams(fn->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(fn->getGenericParams()); writeGenericEnvironment(fn->getGenericSignature(), fn->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -2634,7 +2633,7 @@ void Serializer::writeDecl(const Decl *D) { rawAccessLevel, nameComponents); - writeGenericParams(ctor->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(ctor->getGenericParams()); writeGenericEnvironment(ctor->getGenericSignature(), ctor->getGenericEnvironment(), DeclTypeAbbrCodes); @@ -3014,7 +3013,7 @@ void Serializer::writeType(Type ty) { getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()), fnTy->throws()); if (!genericContext) - writeGenericParams(&fnTy->getGenericParams(), DeclTypeAbbrCodes); + writeGenericParams(&fnTy->getGenericParams()); break; } diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 59e847e87bf44..7f4ae2cbb78dd 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -241,6 +241,9 @@ 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 writeGenericRequirements(ArrayRef requirements); @@ -411,10 +414,6 @@ 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, diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 5f56e23e4089b..d48390259ce50 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -1844,10 +1844,7 @@ void SILSerializer::writeSILBlock(const SILModule *SILMod) { registerSILAbbr(); registerSILAbbr(); registerSILAbbr(); - registerSILAbbr(); - registerSILAbbr(); registerSILAbbr(); - registerSILAbbr(); registerSILAbbr(); for (const SILGlobalVariable &g : SILMod->getSILGlobals()) From 4bfaa4789018e31ab270b4f609194edabca0999e Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 20 Aug 2016 05:10:24 -0700 Subject: [PATCH 07/13] AST: Nuke GenericParamList::AllArchetypes Now that SILFunctions no longer reference a GenericParamList, we don't need to de-serialize cross-module references to archetypes anymore. This was the last remaining usage of AllArchetypes, so we can finally rip it out. --- include/swift/AST/ArchetypeBuilder.h | 5 - include/swift/AST/Decl.h | 33 ---- include/swift/AST/GenericSignature.h | 10 +- include/swift/Serialization/ModuleFormat.h | 5 +- lib/AST/ASTVerifier.cpp | 195 --------------------- lib/AST/ArchetypeBuilder.cpp | 40 ----- lib/AST/Builtins.cpp | 5 +- lib/AST/Decl.cpp | 41 ----- lib/ClangImporter/ImportDecl.cpp | 10 -- lib/Sema/TypeCheckGeneric.cpp | 5 - lib/Serialization/Deserialization.cpp | 57 +----- lib/Serialization/Serialization.cpp | 7 +- 12 files changed, 10 insertions(+), 403 deletions(-) diff --git a/include/swift/AST/ArchetypeBuilder.h b/include/swift/AST/ArchetypeBuilder.h index 43989b9353115..9c7a5b058bfb2 100644 --- a/include/swift/AST/ArchetypeBuilder.h +++ b/include/swift/AST/ArchetypeBuilder.h @@ -323,11 +323,6 @@ 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); diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index f373af38699c6..e1512f05f8922 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1060,7 +1060,6 @@ class GenericParamList final : unsigned NumParams; SourceLoc WhereLoc; MutableArrayRef Requirements; - ArrayRef AllArchetypes; GenericParamList *OuterParameters; @@ -1172,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. @@ -1243,21 +1225,6 @@ class GenericParamList final : return depth; } - /// Derive the all-archetypes list for the given list of generic - /// parameters. - static ArrayRef - deriveAllArchetypes(ArrayRef params, - SmallVectorImpl &archetypes); - - /// 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(); }; 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/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index dde14535d7628..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 = 263; // Last change: remove SILFunction::ContextGenericParams +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. >; diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index f524a5de0abe6..cc14d5d9e0a94 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -2122,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); @@ -2389,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 9db1c79ff2a1d..2bcac2d5204dc 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -170,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; @@ -1766,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; diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index d42c5020d19fe..2b0497597b39d 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -440,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. @@ -449,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); @@ -459,7 +459,6 @@ static GenericParamList *getGenericParams(ASTContext &ctx, auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams, SourceLoc()); - paramList->setAllArchetypes(ctx.AllocateCopy(archetypes)); return paramList; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index ee315ac99ffcc..e10852799cd53 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -536,47 +536,6 @@ void GenericParamList::addTrailingWhereClause( Requirements = newRequirements; } -/// \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) diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 9172239300137..e5added17b282 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -5180,8 +5180,6 @@ namespace { auto *archetype = builder.getArchetype(param); param->setArchetype(archetype); } - genericParams->setAllArchetypes( - Impl.SwiftContext.AllocateCopy(builder.getAllArchetypes())); auto *sig = builder.getGenericSignature(genericParamTypes); auto *env = builder.getGenericEnvironment(genericParamTypes); @@ -5689,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() @@ -6998,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(); diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index 7d9b96dfd53ac..53a79640f4440 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -500,9 +500,6 @@ TypeChecker::markInvalidGenericSignature(DeclContext *DC) { for (auto GP : *genericParams) GP->setArchetype(builder.getArchetype(GP)); - genericParams->setAllArchetypes( - Context.AllocateCopy(builder.getAllArchetypes())); - return genericEnv; } @@ -821,8 +818,6 @@ TypeChecker::finalizeGenericParamList(ArchetypeBuilder &builder, if (!GP->hasAccessibility()) GP->setAccessibility(access); } - genericParams->setAllArchetypes( - Context.AllocateCopy(builder.getAllArchetypes())); #ifndef NDEBUG // Record archetype contexts. diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 34942786a6995..ff1ec85d28ef1 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -665,59 +665,12 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, 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 = DeclTypeCursor.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(); @@ -732,8 +685,6 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC, &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()); diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 0e4054b337940..842116a58fd64 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -958,13 +958,8 @@ bool Serializer::writeGenericParams(const GenericParamList *genericParams) { 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, - archetypeIDs); + GenericParamListLayout::emitRecord(Out, ScratchRecord, abbrCode); abbrCode = DeclTypeAbbrCodes[GenericParamLayout::Code]; for (auto next : genericParams->getParams()) { From 8c9799d9406e5d4205058f47df47941b5f8e9968 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 27 Aug 2016 01:47:03 -0700 Subject: [PATCH 08/13] Sema: Simplify unqualified lookup from protocol extensions Instead of looking at GenericParam requirements, look at the generic signature. --- lib/Sema/TypeCheckType.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 94e9f9fbbbfbb..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()); } } } From 71cadae0f96a11c517bf3284084e6254cc3e5be7 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 27 Aug 2016 14:25:34 -0700 Subject: [PATCH 09/13] Sema: Change a few isGenericContext() checks to getGenericSignatureOfContext() --- lib/Sema/TypeCheckDecl.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index db84a014b9724..6ab832aa27627 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -4739,7 +4739,7 @@ class DeclChecker : public DeclVisitor { 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)) { auto *env = TC.markInvalidGenericSignature(FD); FD->setGenericEnvironment(env); @@ -4760,7 +4760,7 @@ class DeclChecker : public DeclVisitor { if (semaFuncDecl(FD, &resolver)) return; - if (!FD->isGenericContext()) + if (!FD->getGenericSignatureOfContext()) TC.configureInterfaceType(FD); if (FD->isInvalid()) @@ -6146,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(); @@ -6242,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. @@ -6422,7 +6422,7 @@ class DeclChecker : public DeclVisitor { 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)) { auto *env = TC.markInvalidGenericSignature(CD); CD->setGenericEnvironment(env); @@ -6444,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); } @@ -6579,7 +6579,7 @@ 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()); @@ -6591,7 +6591,7 @@ class DeclChecker : public DeclVisitor { DD->setInvalid(); } - if (!DD->isGenericContext()) + if (!DD->getGenericSignatureOfContext()) TC.configureInterfaceType(DD); if (!DD->hasType()) { From e72808c1ce0aa0a30e6e24d4880dcecd6724c1b4 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 26 Aug 2016 03:09:47 -0700 Subject: [PATCH 10/13] Fixed SIL crashers --- .../SIL/crashers/025-swift-typechecker-resolvetype.sil | 3 --- .../028-swift-genericsignature-getcanonicalsignature.sil | 3 --- ...08-swift-genericparamlist-getasgenericsignatureelements.sil | 2 +- .../021-swift-typechecker-typecheckdecl.sil | 2 +- .../SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil | 3 +++ .../028-swift-genericsignature-getcanonicalsignature.sil | 3 +++ 6 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 validation-test/SIL/crashers/025-swift-typechecker-resolvetype.sil delete mode 100644 validation-test/SIL/crashers/028-swift-genericsignature-getcanonicalsignature.sil rename validation-test/SIL/{crashers => crashers_fixed}/008-swift-genericparamlist-getasgenericsignatureelements.sil (56%) rename validation-test/SIL/{crashers => crashers_fixed}/021-swift-typechecker-typecheckdecl.sil (54%) create mode 100644 validation-test/SIL/crashers_fixed/025-swift-typechecker-resolvetype.sil create mode 100644 validation-test/SIL/crashers_fixed/028-swift-genericsignature-getcanonicalsignature.sil 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:$(<τ>()->( From 1b11d9d4c3d5f1986146b481d64880310cb7ea24 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Fri, 26 Aug 2016 03:10:14 -0700 Subject: [PATCH 11/13] Teach resolve-crashers.py to resolve SIL crashers --- utils/resolve-crashes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From 1c4185525ade5ac87544523b493ee65c77598fe4 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 28 Aug 2016 13:58:56 -0700 Subject: [PATCH 12/13] Sema: Targeted fix for a crasher that regressed with AllArchetypes changes I've got a big overhaul of collectRequirements() coming shortly, so I'm not going to bother fixing this properly here. --- lib/AST/ArchetypeBuilder.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp index 2bcac2d5204dc..f21f4e60dcc50 100644 --- a/lib/AST/ArchetypeBuilder.cpp +++ b/lib/AST/ArchetypeBuilder.cpp @@ -2130,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); } From 97d05629135d68fdc776e36c23940e79bfad6d4a Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sun, 28 Aug 2016 13:59:20 -0700 Subject: [PATCH 13/13] XFAIL a crasher that no longer crashes with removal of AllArchetypes The code here should not type check, because we're adding a requirement to an outer archetype. I'm working on some changes to ArchetypeBuilder that will make this kind of thing easier to catch. --- validation-test/compiler_crashers/28369-swift-decl-walk.swift | 1 + 1 file changed, 1 insertion(+) 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 {