diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index cf06cb1c903..48e5a99badf 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -34,6 +34,7 @@ #include "swift/AST/TypeAlignments.h" #include "swift/AST/TypeExpansionContext.h" #include "swift/Basic/ArrayRefView.h" +#include "swift/Basic/Assertions.h" #include "swift/Basic/Debug.h" #include "swift/Basic/InlineBitfield.h" #include "swift/Basic/UUID.h" @@ -562,6 +563,13 @@ protected: assert(Bits.TypeBase.Properties == properties.getBits() && "Bits dropped!"); } + /// This is used when constructing GenericTypeParamTypes. + void setCanonicalType(CanType type) { + DEBUG_ASSERT(!Bits.TypeBase.IsCanonical); + DEBUG_ASSERT(CanonicalType.isNull()); + CanonicalType = type; + } + public: /// getKind - Return what kind of type this is. TypeKind getKind() const { return static_cast(Bits.TypeBase.Kind); } @@ -6966,12 +6974,17 @@ const Type *ArchetypeType::getSubclassTrailingObjects() const { /// \sa GenericTypeParamDecl class GenericTypeParamType : public SubstitutableType, public llvm::FoldingSetNode { - static constexpr unsigned TYPE_SEQUENCE_BIT = (1 << 30); + /// A canonical generic parameter type is given by a depth, index, parameter + /// kind, and an optional value type. A sugared generic parameter type stores + /// a declaration or an identifier. + union { + GenericTypeParamDecl *Decl; + Identifier Name; + }; - using DepthIndexTy = llvm::PointerEmbeddedInt; - - /// The generic type parameter or depth/index. - llvm::PointerUnion ParamOrDepthIndex; + unsigned Depth : 15; + unsigned IsDecl : 1; + unsigned Index : 16; /// The kind of generic type parameter this is. GenericTypeParamKind ParamKind; @@ -6984,31 +6997,36 @@ class GenericTypeParamType : public SubstitutableType, Type ValueType; public: + /// Retrieve a sugared generic type parameter type. + /// + /// Note: This should only be called by the InterfaceTypeRequest. + static GenericTypeParamType *get(GenericTypeParamDecl *decl); - /// Retrieve a generic type parameter with the given kind, depth, index, and - /// optional value type. + /// Retrieve a sugared generic type parameter at the given depth and index. + static GenericTypeParamType *get(Identifier name, + GenericTypeParamKind paramKind, + unsigned depth, unsigned index, + Type valueType, const ASTContext &ctx); + + /// Retrieve a canonical generic type parameter with the given kind, depth, + /// index, and optional value type. static GenericTypeParamType *get(GenericTypeParamKind paramKind, unsigned depth, unsigned index, Type valueType, const ASTContext &ctx); - /// Retrieve a generic type parameter at the given depth and index. + /// Retrieve a canonical generic type parameter at the given depth and index. static GenericTypeParamType *getType(unsigned depth, unsigned index, const ASTContext &ctx); - /// Retrieve a generic parameter pack at the given depth and index. + /// Retrieve a canonical generic parameter pack at the given depth and index. static GenericTypeParamType *getPack(unsigned depth, unsigned index, const ASTContext &ctx); - /// Retrieve a generic value parameter at the given depth and index with the - /// given value type. + /// Retrieve a canonical generic value parameter at the given depth and index + /// with the given value type. static GenericTypeParamType *getValue(unsigned depth, unsigned index, Type valueType, const ASTContext &ctx); - /// Retrieve a generic type parameter for the given generic type param decl. - /// - /// Note: This should only be called by the GenericTypeParamDecl constructor. - static GenericTypeParamType *get(GenericTypeParamDecl *param); - /// If this is an opaque parameter, return the declaration of the /// parameter, otherwise null. GenericTypeParamDecl *getOpaqueDecl() const; @@ -7016,7 +7034,7 @@ public: /// Retrieve the declaration of the generic type parameter, or null if /// there is no such declaration. GenericTypeParamDecl *getDecl() const { - return ParamOrDepthIndex.dyn_cast(); + return (IsDecl ? Decl : nullptr); } /// Retrieve the kind of generic type parameter this type is referencing. @@ -7037,7 +7055,9 @@ public: /// \endcode /// /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0. - unsigned getDepth() const; + unsigned getDepth() const { + return Depth; + } /// The index of this generic type parameter within its generic parameter /// list. @@ -7049,7 +7069,9 @@ public: /// \endcode /// /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0. - unsigned getIndex() const; + unsigned getIndex() const { + return Index; + } /// Returns \c true if this type parameter is declared as a pack. /// @@ -7073,14 +7095,17 @@ public: Type getValueType() const; void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getParamKind(), getDepth(), getIndex(), getValueType()); + Profile(ID, getParamKind(), getDepth(), getIndex(), getValueType(), + getName()); } - static void Profile(llvm::FoldingSetNodeID &ID, GenericTypeParamKind paramKind, - unsigned depth, unsigned index, Type valueType) { + static void Profile(llvm::FoldingSetNodeID &ID, + GenericTypeParamKind paramKind, unsigned depth, + unsigned index, Type valueType, Identifier name) { ID.AddInteger((uint8_t)paramKind); ID.AddInteger(depth); ID.AddInteger(index); ID.AddPointer(valueType.getPointer()); + ID.AddPointer(name.get()); } // Implement isa/cast/dyncast/etc. @@ -7091,16 +7116,19 @@ public: private: friend class GenericTypeParamDecl; - explicit GenericTypeParamType(RecursiveTypeProperties props) - : SubstitutableType(TypeKind::GenericTypeParam, nullptr, props) {} + explicit GenericTypeParamType(GenericTypeParamDecl *param, + RecursiveTypeProperties props); - explicit GenericTypeParamType(GenericTypeParamKind paramKind, - unsigned depth, unsigned index, Type valueType, + /// Note: We have no way to recover an ASTContext from an Identifier, so the + /// initialization of an identifier-sugared generic parameter type receives + /// the canonical type. + explicit GenericTypeParamType(Identifier name, GenericTypeParamType *canType, + const ASTContext &ctx); + + explicit GenericTypeParamType(GenericTypeParamKind paramKind, unsigned depth, + unsigned index, Type valueType, RecursiveTypeProperties props, - const ASTContext &ctx) - : SubstitutableType(TypeKind::GenericTypeParam, &ctx, props), - ParamOrDepthIndex(depth << 16 | index), - ParamKind(paramKind), ValueType(valueType) {} + const ASTContext &ctx); }; BEGIN_CAN_TYPE_WRAPPER(GenericTypeParamType, SubstitutableType) static CanGenericTypeParamType getType(unsigned depth, unsigned index, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d2ecc6ed970..5a7050dc254 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4755,12 +4755,14 @@ GenericFunctionType::GenericFunctionType( } } -GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamKind paramKind, +GenericTypeParamType *GenericTypeParamType::get(Identifier name, + GenericTypeParamKind paramKind, unsigned depth, unsigned index, Type valueType, const ASTContext &ctx) { llvm::FoldingSetNodeID id; - GenericTypeParamType::Profile(id, paramKind, depth, index, valueType); + GenericTypeParamType::Profile(id, paramKind, depth, index, valueType, + name); void *insertPos; if (auto gpTy = ctx.getImpl().GenericParamTypes.FindNodeOrInsertPos(id, insertPos)) @@ -4776,6 +4778,23 @@ GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamKind paramKind, return result; } +GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamDecl *param) { + RecursiveTypeProperties props = RecursiveTypeProperties::HasTypeParameter; + if (param->isParameterPack()) + props |= RecursiveTypeProperties::HasParameterPack; + + return new (param->getASTContext(), AllocationArena::Permanent) + GenericTypeParamType(param, props); +} + +GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamKind paramKind, + unsigned depth, unsigned index, + Type valueType, + const ASTContext &ctx) { + return GenericTypeParamType::get(Identifier(), paramKind, depth, index, + valueType, ctx); +} + GenericTypeParamType *GenericTypeParamType::getType(unsigned depth, unsigned index, const ASTContext &ctx) { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index bea35b05f4a..24ae3f91af7 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5670,10 +5670,6 @@ GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name, if (this->isValue()) *getTrailingObjects() = specifierLoc; - - auto &ctx = dc->getASTContext(); - auto type = GenericTypeParamType::get(this); - setInterfaceType(MetatypeType::get(type, ctx)); } GenericTypeParamDecl *GenericTypeParamDecl::create( diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ee7f3897ea1..f5aeddf2e63 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1663,21 +1663,11 @@ CanType TypeBase::computeCanonicalType() { case TypeKind::GenericTypeParam: { GenericTypeParamType *gp = cast(this); auto gpDecl = gp->getDecl(); - - // If we haven't set a depth for this generic parameter, try to do so. - // FIXME: This is a dreadful hack. - if (gpDecl->getDepth() == GenericTypeParamDecl::InvalidDepth) { - auto *dc = gpDecl->getDeclContext(); - auto *gpList = dc->getAsDecl()->getAsGenericContext()->getGenericParams(); - gpList->setDepth(dc->getGenericContextDepth()); - } - - assert(gpDecl->getDepth() != GenericTypeParamDecl::InvalidDepth && - "parameter hasn't been validated"); + auto &C = gpDecl->getASTContext(); Result = - GenericTypeParamType::get(gpDecl->getParamKind(), gpDecl->getDepth(), - gpDecl->getIndex(), gpDecl->getValueType(), - gpDecl->getASTContext()); + GenericTypeParamType::get(gp->getParamKind(), gp->getDepth(), + gp->getIndex(), gp->getValueType(), + C); break; } @@ -1986,35 +1976,46 @@ ArrayRef TypeAliasType::getDirectGenericArgs() const { return getSubstitutionMap().getInnermostReplacementTypes(); } -GenericTypeParamType *GenericTypeParamType::get(GenericTypeParamDecl *param) { - auto &ctx = param->getASTContext(); - - RecursiveTypeProperties props = RecursiveTypeProperties::HasTypeParameter; - if (param->isParameterPack()) - props |= RecursiveTypeProperties::HasParameterPack; - - auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(props); - type->ParamOrDepthIndex = param; - type->ParamKind = param->getParamKind(); - return type; +GenericTypeParamType::GenericTypeParamType(GenericTypeParamDecl *param, + RecursiveTypeProperties props) + : SubstitutableType(TypeKind::GenericTypeParam, nullptr, props), + Decl(param) { + ASSERT(param->getDepth() != GenericTypeParamDecl::InvalidDepth); + Depth = param->getDepth(); + IsDecl = true; + Index = param->getIndex(); + ParamKind = param->getParamKind(); + ValueType = param->getValueType(); } -unsigned GenericTypeParamType::getDepth() const { - if (auto param = getDecl()) { - return param->getDepth(); - } +GenericTypeParamType::GenericTypeParamType(Identifier name, + GenericTypeParamType *canType, + const ASTContext &ctx) + : SubstitutableType(TypeKind::GenericTypeParam, nullptr, + canType->getRecursiveProperties()), + Decl(nullptr) { + Name = name; + Depth = canType->getDepth(); + IsDecl = false; + Index = canType->getIndex(); + ParamKind = canType->getParamKind(); + ValueType = canType->getValueType(); - auto fixedNum = ParamOrDepthIndex.get(); - return (fixedNum & ~GenericTypeParamType::TYPE_SEQUENCE_BIT) >> 16; + setCanonicalType(CanType(canType)); } -unsigned GenericTypeParamType::getIndex() const { - if (auto param = getDecl()) { - return param->getIndex(); - } - - auto fixedNum = ParamOrDepthIndex.get(); - return fixedNum & 0xFFFF; +GenericTypeParamType::GenericTypeParamType(GenericTypeParamKind paramKind, + unsigned depth, unsigned index, + Type valueType, + RecursiveTypeProperties props, + const ASTContext &ctx) + : SubstitutableType(TypeKind::GenericTypeParam, &ctx, props), + Decl(nullptr) { + Depth = depth; + IsDecl = false; + Index = index; + ParamKind = paramKind; + ValueType = valueType; } GenericTypeParamDecl *GenericTypeParamType::getOpaqueDecl() const { @@ -2028,14 +2029,19 @@ Identifier GenericTypeParamType::getName() const { // Use the declaration name if we still have that sugar. if (auto decl = getDecl()) return decl->getName(); - + + if (!isCanonical()) + return Name; + // Otherwise, we're canonical. Produce an anonymous '_n_n' name. - assert(isCanonical()); + // getASTContext() doesn't actually mutate an already-canonical type. auto &C = const_cast(this)->getASTContext(); auto &names = C.CanonicalGenericTypeParamTypeNames; - unsigned depthIndex = ParamOrDepthIndex.get(); - auto cached = names.find(depthIndex); + + auto key = (getDepth() << 16) | getIndex(); + + auto cached = names.find(key); if (cached != names.end()) return cached->second; @@ -2046,7 +2052,7 @@ Identifier GenericTypeParamType::getName() const { os << tau << getDepth() << '_' << getIndex(); Identifier name = C.getIdentifier(os.str()); - names.insert({depthIndex, name}); + names.insert({key, name}); return name; } diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 1aec8fc05f7..4250e3ca00c 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2418,11 +2418,24 @@ InterfaceTypeRequest::evaluate(Evaluator &eval, ValueDecl *D) const { case DeclKind::MissingMember: case DeclKind::Module: case DeclKind::OpaqueType: - case DeclKind::GenericTypeParam: case DeclKind::MacroExpansion: llvm_unreachable("should not get here"); return Type(); + case DeclKind::GenericTypeParam: { + auto *paramDecl = cast(D); + + // If we haven't set a depth for this generic parameter yet, do so. + if (paramDecl->getDepth() == GenericTypeParamDecl::InvalidDepth) { + auto *dc = paramDecl->getDeclContext(); + auto *gpList = dc->getAsDecl()->getAsGenericContext()->getGenericParams(); + gpList->setDepth(dc->getGenericContextDepth()); + } + + auto type = GenericTypeParamType::get(paramDecl); + return MetatypeType::get(type, Context); + } + case DeclKind::AssociatedType: { auto assocType = cast(D); auto interfaceTy = assocType->getDeclaredInterfaceType(); diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 989048cba23..bd891d51f0a 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -7327,19 +7327,22 @@ Expected DESERIALIZE_TYPE(GENERIC_TYPE_PARAM_TYPE)( ModuleFile &MF, SmallVectorImpl &scratch, StringRef blobData) { unsigned rawParamKind; - DeclID declIDOrDepth; - unsigned indexPlusOne; + bool hasDecl; + unsigned depth; + unsigned index; + DeclID declOrIdentifier; TypeID valueTypeID; decls_block::GenericTypeParamTypeLayout::readRecord( - scratch, rawParamKind, declIDOrDepth, indexPlusOne, valueTypeID); + scratch, rawParamKind, hasDecl, depth, index, declOrIdentifier, + valueTypeID); auto paramKind = getActualParamKind(rawParamKind); if (!paramKind) return MF.diagnoseFatal(); - if (indexPlusOne == 0) { - auto genericParamOrError = MF.getDeclChecked(declIDOrDepth); + if (hasDecl) { + auto genericParamOrError = MF.getDeclChecked(declOrIdentifier); if (!genericParamOrError) return genericParamOrError.takeError(); @@ -7348,6 +7351,10 @@ DESERIALIZE_TYPE(GENERIC_TYPE_PARAM_TYPE)( if (!genericParam) return MF.diagnoseFatal(); + ASSERT(*paramKind == genericParam->getParamKind()); + ASSERT(depth == genericParam->getDepth()); + ASSERT(index == genericParam->getIndex()); + return genericParam->getDeclaredInterfaceType(); } @@ -7355,8 +7362,13 @@ DESERIALIZE_TYPE(GENERIC_TYPE_PARAM_TYPE)( if (!valueType) return valueType.takeError(); - return GenericTypeParamType::get(*paramKind, declIDOrDepth, - indexPlusOne - 1, valueType.get(), + if (declOrIdentifier == 0) { + return GenericTypeParamType::get(*paramKind, depth, index, *valueType, + MF.getContext()); + } + + auto name = MF.getDeclBaseName(declOrIdentifier).getIdentifier(); + return GenericTypeParamType::get(name, *paramKind, depth, index, *valueType, MF.getContext()); } diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 58a9ca8b259..d285331587d 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -1222,11 +1222,12 @@ namespace decls_block { TYPE_LAYOUT(GenericTypeParamTypeLayout, GENERIC_TYPE_PARAM_TYPE, - GenericParamKindField, // param kind - DeclIDField, // generic type parameter decl or depth - BCVBR<4>, // index + 1, or zero if we have a generic type - // parameter decl - TypeIDField // value type (if param kind == Value) + GenericParamKindField, // param kind + BCFixed<1>, // has decl? + BCFixed<15>, // depth + BCFixed<16>, // index + DeclIDField, // generic type parameter decl or identifier + TypeIDField // value type (if param kind == Value) ); TYPE_LAYOUT(DependentMemberTypeLayout, diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 68fad797c41..eb32bb621ec 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5568,18 +5568,18 @@ public: using namespace decls_block; unsigned abbrCode = S.DeclTypeAbbrCodes[GenericTypeParamTypeLayout::Code]; - DeclID declIDOrDepth; - unsigned indexPlusOne; + DeclID declOrIdentifier = 0; + bool hasDecl = false; uint8_t paramKind = getRawStableGenericParamKind(genericParam->getParamKind()); - TypeID valueTypeID; + TypeID valueTypeID = 0; + if (genericParam->getDecl() && !(genericParam->getDecl()->getDeclContext()->isModuleScopeContext() && S.isDeclXRef(genericParam->getDecl()))) { - declIDOrDepth = S.addDeclRef(genericParam->getDecl()); - indexPlusOne = 0; - } else { - declIDOrDepth = genericParam->getDepth(); - indexPlusOne = genericParam->getIndex() + 1; + declOrIdentifier = S.addDeclRef(genericParam->getDecl()); + hasDecl = true; + } else if (!genericParam->isCanonical()) { + declOrIdentifier = S.addDeclBaseNameRef(genericParam->getName()); } if (auto valueType = genericParam->getValueType()) { @@ -5587,8 +5587,12 @@ public: } GenericTypeParamTypeLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode, - paramKind, declIDOrDepth, - indexPlusOne, valueTypeID); + paramKind, + hasDecl, + genericParam->getDepth(), + genericParam->getIndex(), + declOrIdentifier, + valueTypeID); } void visitDependentMemberType(const DependentMemberType *dependent) {