diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 4e7ec41a421..65862a5c3d3 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -680,6 +680,14 @@ public: void setOuterParameters(GenericParamList *Outer) { OuterParameters = Outer; } SourceRange getSourceRange() const { return Brackets; } + + /// Retrieve the depth of this generic parameter list. + unsigned getDepth() const { + unsigned depth = 0; + for (auto gp = getOuterParameters(); gp; gp = gp->getOuterParameters()) + ++depth; + return depth; + } }; /// Describes what kind of name is being imported. @@ -1267,6 +1275,8 @@ public: class GenericTypeParamDecl : public AbstractTypeParamDecl { /// The location of the name. SourceLoc NameLoc; + unsigned Depth : 16; + unsigned Index : 16; public: /// Construct a new generic type parameter. @@ -1277,8 +1287,38 @@ public: /// /// \param name The name of the generic parameter. /// \param nameLoc The location of the name. - GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc); - + GenericTypeParamDecl(DeclContext *dc, Identifier name, SourceLoc nameLoc, + unsigned depth, unsigned index); + + /// The depth of this generic type parameter, i.e., the number of outer + /// levels of generic parameter lists that enclose this type parameter. + /// + /// \code + /// struct X { + /// func f() { } + /// } + /// \endcode + /// + /// Here 'T' has depth 0 and 'U' has depth 0. Both have index 0. + unsigned getDepth() const { return Depth; } + + /// Set the depth of this generic type parameter. + /// + /// \sa getDepth + void setDepth(unsigned depth) { Depth = depth; } + + /// The index of this generic type parameter within its generic parameter + /// list. + /// + /// \code + /// struct X { + /// func f() { } + /// } + /// \endcode + /// + /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0. + unsigned getIndex() const { return Index; } + SourceLoc getStartLoc() const { return NameLoc; } SourceLoc getLoc() const { return NameLoc; } SourceRange getSourceRange() const; diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index f1a4c37ac34..a80f9727379 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -1918,6 +1918,30 @@ public: /// sugar until we get down to a non-sugar type. TypeBase *getDesugaredType(); + /// The depth of this generic type parameter, i.e., the number of outer + /// levels of generic parameter lists that enclose this type parameter. + /// + /// \code + /// struct X { + /// func f() { } + /// } + /// \endcode + /// + /// Here 'T' has depth 0 and 'U' has depth 0. Both have index 0. + unsigned getDepth() const; + + /// The index of this generic type parameter within its generic parameter + /// list. + /// + /// \code + /// struct X { + /// func f() { } + /// } + /// \endcode + /// + /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0. + unsigned getIndex() const; + // Implement isa/cast/dyncast/etc. static bool classof(const TypeBase *T) { return T->getKind() == TypeKind::GenericTypeParam; diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index f88a0e18d6c..3b59c1bf81c 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -267,7 +267,7 @@ getGenericParam(ASTContext &Context) { Type(), 0); auto GenericTyDecl = new (Context) GenericTypeParamDecl(Context.TheBuiltinModule, GenericName, - SourceLoc()); + SourceLoc(), 0, 0); GenericTyDecl->setArchetype(Archetype); Type GenericTy = GenericTyDecl->getDeclaredType(); GenericParam Param = GenericTyDecl; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index eb67a7ddc17..b9383ec2342 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -554,9 +554,10 @@ SourceRange TypeAliasDecl::getSourceRange() const { } GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name, - SourceLoc nameLoc) + SourceLoc nameLoc, + unsigned depth, unsigned index) : AbstractTypeParamDecl(DeclKind::GenericTypeParam, dc, name), - NameLoc(nameLoc) + NameLoc(nameLoc), Depth(depth), Index(index) { auto &ctx = dc->getASTContext(); auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(this); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0e4d89dddf9..905ebc59387 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -982,6 +982,14 @@ TypeBase *GenericTypeParamType::getDesugaredType() { return getDecl()->getArchetype()->getDesugaredType(); } +unsigned GenericTypeParamType::getDepth() const { + return Param->getDepth(); +} + +unsigned GenericTypeParamType::getIndex() const { + return Param->getIndex(); +} + TypeBase *AssociatedTypeType::getDesugaredType() { return getDecl()->getArchetype()->getDesugaredType(); } diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp index 552e53085dc..d87d90ae6ea 100644 --- a/lib/Parse/ParseGeneric.cpp +++ b/lib/Parse/ParseGeneric.cpp @@ -71,8 +71,12 @@ GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) { Inherited.push_back(Ty.get()); } + // We always create generic type parameters with a depth of zero. + // Semantic analysis fills in the depth when it processes the generic + // parameter list. auto Param = new (Context) GenericTypeParamDecl(CurDeclContext, Name, - NameLoc); + NameLoc, /*Depth=*/0, + GenericParams.size()); if (!Inherited.empty()) Param->setInherited(Context.AllocateCopy(Inherited)); GenericParams.push_back(Param); diff --git a/lib/SIL/Mangle.cpp b/lib/SIL/Mangle.cpp index fffc46297d6..888f4ac7b51 100644 --- a/lib/SIL/Mangle.cpp +++ b/lib/SIL/Mangle.cpp @@ -290,14 +290,8 @@ void Mangler::bindGenericParameters(const GenericParamList *genericParams, // Determine the depth our parameter list is at. We don't actually need to // emit the outer parameters because they should have been emitted as part of // the outer context. - const GenericParamList *parent = genericParams; - ArchetypesDepth = 0; - do { - ++ArchetypesDepth; - } while ((parent = parent->getOuterParameters())); - + ArchetypesDepth = genericParams->getDepth() + 1; unsigned index = 0; - for (auto archetype : genericParams->getAllArchetypes()) { // Remember the current depth and level. ArchetypeInfo info; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 0c4426d60c6..9a2b5ba13b4 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -415,6 +415,7 @@ public: void checkGenericParams(GenericParamList *GenericParams) { assert(GenericParams && "Missing generic parameters"); + unsigned Depth = GenericParams->getDepth(); // Assign archetypes to each of the generic parameters. ArchetypeBuilder Builder = createArchetypeBuilder(); @@ -422,6 +423,9 @@ public: for (auto GP : *GenericParams) { auto TypeParam = GP.getAsTypeParam(); + // Set the depth of this type parameter. + TypeParam->setDepth(Depth); + // Check the constraints on the type parameter. checkInheritanceClause(TC, TypeParam); diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index e063f4b6284..92b82cbb74a 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -698,11 +698,15 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext, case decls_block::GENERIC_TYPE_PARAM_DECL: { IdentifierID nameID; DeclID contextID; + unsigned depth; + unsigned index; TypeID superclassID; TypeID archetypeID; decls_block::GenericTypeParamDeclLayout::readRecord(scratch, nameID, contextID, + depth, + index, superclassID, archetypeID); @@ -713,7 +717,9 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext, auto genericParam = new (ctx) GenericTypeParamDecl(DC, getIdentifier(nameID), - SourceLoc()); + SourceLoc(), + depth, + index); declOrOffset = genericParam; genericParam->setSuperclass(getType(superclassID)); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 3e657c8e2fd..2a4c0141888 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -467,6 +467,8 @@ namespace decls_block { GENERIC_TYPE_PARAM_DECL, IdentifierIDField, // name DeclIDField, // context decl + BCVBR<4>, // depth + BCVBR<4>, // index TypeIDField, // superclass type TypeIDField // archetype type // Trailed by the conformance info (if any). diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 224a6b4316d..a3fe12859ae 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1022,18 +1022,8 @@ bool Serializer::writeCrossReference(const Decl *D) { kind = XRefKind::SwiftValue; if (auto genericParam = dyn_cast(D)) { - DeclContext *DC = genericParam->getDeclContext(); - auto params = DC->getGenericParamsOfContext()->getParams(); - - auto iter = std::find_if(params.begin(), params.end(), - [=](const GenericParam ¶m) { - return param.getAsTypeParam() == genericParam; - }); - assert(iter != params.end() && "generic param not in list"); - - // FIXME: Record the index in the GenericTypeParamDecl. kind = XRefKind::SwiftGenericParameter; - typeID = std::distance(params.begin(), iter); + typeID = genericParam->getIndex(); } if (kind == XRefKind::SwiftValue) { @@ -1232,6 +1222,8 @@ bool Serializer::writeDecl(const Decl *D) { GenericTypeParamDeclLayout::emitRecord(Out, ScratchRecord, abbrCode, addIdentifierRef(genericParam->getName()), addDeclRef(DC), + genericParam->getDepth(), + genericParam->getIndex(), addTypeRef(genericParam->getSuperclass()), addTypeRef(genericParam->getArchetype()));