Merge pull request #5961 from DougGregor/archetype-representation
[AST] Improve the representation of `ArchetypeType`
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 46456c8..b98f548 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -3822,9 +3822,7 @@
Type Superclass;
llvm::PointerUnion<ArchetypeType *, TypeBase *> ParentOrOpened;
- AssociatedTypeDecl *AssocType;
- Identifier Name;
- unsigned isRecursive: 1;
+ llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName;
MutableArrayRef<std::pair<Identifier, NestedType>> NestedTypes;
/// Set the ID number of this opened existential.
@@ -3843,21 +3841,18 @@
static CanTypeWrapper<ArchetypeType>
getNew(const ASTContext &Ctx, ArchetypeType *Parent,
AssociatedTypeDecl *AssocType,
- Identifier Name, ArrayRef<Type> ConformsTo,
- Type Superclass,
- bool isRecursive = false);
+ SmallVectorImpl<ProtocolDecl *> &ConformsTo,
+ Type Superclass);
/// getNew - Create a new archetype with the given name.
///
/// The ConformsTo array will be minimized then copied into the ASTContext
/// by this routine.
static CanTypeWrapper<ArchetypeType>
- getNew(const ASTContext &Ctx, ArchetypeType *Parent,
- AssociatedTypeDecl *AssocType,
+ getNew(const ASTContext &Ctx,
Identifier Name,
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
- Type Superclass,
- bool isRecursive = false);
+ Type Superclass);
/// Create a new archetype that represents the opened type
/// of an existential value.
@@ -3877,7 +3872,7 @@
static CanType getAnyOpened(Type existential);
/// \brief Retrieve the name of this archetype.
- Identifier getName() const { return Name; }
+ Identifier getName() const;
/// \brief Retrieve the fully-dotted name that should be used to display this
/// archetype.
@@ -3901,7 +3896,7 @@
/// be a member of one of the protocols to which the parent archetype
/// conforms.
AssociatedTypeDecl *getAssocType() const {
- return AssocType;
+ return AssocTypeOrName.dyn_cast<AssociatedTypeDecl *>();
}
/// getConformsTo - Retrieve the set of protocols to which this substitutable
@@ -3971,34 +3966,28 @@
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::Archetype;
}
-
- /// getIsRecursive - The archetype type refers back to itself.
- bool getIsRecursive() { return this->isRecursive; }
-
+
private:
- ArchetypeType(const ASTContext &Ctx, ArchetypeType *Parent,
- AssociatedTypeDecl *AssocType,
- Identifier Name, ArrayRef<ProtocolDecl *> ConformsTo,
- Type Superclass,
- bool isRecursive = false)
+ ArchetypeType(
+ const ASTContext &Ctx, ArchetypeType *Parent,
+ llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName,
+ ArrayRef<ProtocolDecl *> ConformsTo,
+ Type Superclass)
: SubstitutableType(TypeKind::Archetype, &Ctx,
RecursiveTypeProperties::HasArchetype),
ConformsTo(ConformsTo), Superclass(Superclass), ParentOrOpened(Parent),
- AssocType(AssocType), Name(Name),
- isRecursive(isRecursive) { }
+ AssocTypeOrName(AssocTypeOrName) { }
ArchetypeType(const ASTContext &Ctx,
Type Existential,
ArrayRef<ProtocolDecl *> ConformsTo,
- Type Superclass, bool isRecursive = false)
+ Type Superclass)
: SubstitutableType(TypeKind::Archetype, &Ctx,
RecursiveTypeProperties(
RecursiveTypeProperties::HasArchetype |
RecursiveTypeProperties::HasOpenedExistential)),
ConformsTo(ConformsTo), Superclass(Superclass),
- ParentOrOpened(Existential.getPointer()),
- AssocType(nullptr),
- isRecursive(isRecursive) { }
+ ParentOrOpened(Existential.getPointer()) { }
};
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
CanArchetypeType getParent() const {
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 27a0870..889ad45 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// 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 = 284; // Last change: Self archetype protocol removed
+const uint16_t VERSION_MINOR = 285; // Last change: simplified archetype format
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
@@ -624,9 +624,8 @@
using ArchetypeTypeLayout = BCRecordLayout<
ARCHETYPE_TYPE,
- IdentifierIDField, // name
- TypeIDField, // index if primary, parent if non-primary
- DeclIDField, // associated type decl
+ TypeIDField, // parent if non-primary
+ DeclIDField, // associated type decl if non-primary, name if primary
TypeIDField, // superclass
BCArray<DeclIDField> // conformances
// Trailed by the nested types record.
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 499c79a..29f0c34 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -489,9 +489,6 @@
defaultDef.print(OS);
}
- if (decl->isRecursive())
- OS << " <<RECURSIVE>>";
-
OS << ")";
}
diff --git a/lib/AST/ArchetypeBuilder.cpp b/lib/AST/ArchetypeBuilder.cpp
index 0b04fbb..23bcd78 100644
--- a/lib/AST/ArchetypeBuilder.cpp
+++ b/lib/AST/ArchetypeBuilder.cpp
@@ -711,10 +711,24 @@
}
}
- auto arch
- = ArchetypeType::getNew(builder.getASTContext(), ParentArchetype,
- assocType, getName(), Protos,
- superclass, isRecursive());
+ ArchetypeType *arch;
+ if (ParentArchetype) {
+ // If we were unable to resolve this as an associated type, produce an
+ // error type.
+ if (!assocType) {
+ representative->ArchetypeOrConcreteType =
+ NestedType::forConcreteType(
+ ErrorType::get(getDependentType(builder, true)));
+
+ return representative->ArchetypeOrConcreteType;
+ }
+
+ arch = ArchetypeType::getNew(builder.getASTContext(), ParentArchetype,
+ assocType, Protos, superclass);
+ } else {
+ arch = ArchetypeType::getNew(builder.getASTContext(), getName(), Protos,
+ superclass);
+ }
representative->ArchetypeOrConcreteType = NestedType::forArchetype(arch);
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index 08e6a4d..57d9ca0 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -432,10 +432,8 @@
createGenericParam(ASTContext &ctx, const char *name, unsigned index) {
Module *M = ctx.TheBuiltinModule;
Identifier ident = ctx.getIdentifier(name);
- ArchetypeType *archetype
- = ArchetypeType::getNew(ctx, nullptr,
- static_cast<AssociatedTypeDecl *>(nullptr),
- ident, ArrayRef<Type>(), Type(), false);
+ SmallVector<ProtocolDecl *, 1> protos;
+ ArchetypeType *archetype = ArchetypeType::getNew(ctx, ident, protos, Type());
auto genericParam =
new (ctx) GenericTypeParamDecl(&M->getMainFile(FileUnitKind::Builtin),
ident, SourceLoc(), 0, index);
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 44833db..95b1888 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2490,41 +2490,34 @@
}
-CanArchetypeType ArchetypeType::getNew(const ASTContext &Ctx,
- ArchetypeType *Parent,
- AssociatedTypeDecl *AssocType,
- Identifier Name,
- ArrayRef<Type> ConformsTo,
- Type Superclass,
- bool isRecursive) {
- // Gather the set of protocol declarations to which this archetype conforms.
- SmallVector<ProtocolDecl *, 4> ConformsToProtos;
- for (auto P : ConformsTo) {
- addProtocols(P, ConformsToProtos);
- }
- ProtocolType::canonicalizeProtocols(ConformsToProtos);
-
- auto arena = AllocationArena::Permanent;
- return CanArchetypeType(
- new (Ctx, arena) ArchetypeType(Ctx, Parent, AssocType, Name,
- Ctx.AllocateCopy(ConformsToProtos),
- Superclass, isRecursive));
-}
-
-CanArchetypeType
-ArchetypeType::getNew(const ASTContext &Ctx, ArchetypeType *Parent,
- AssociatedTypeDecl *AssocType,
- Identifier Name,
- SmallVectorImpl<ProtocolDecl *> &ConformsTo,
- Type Superclass, bool isRecursive) {
+CanArchetypeType ArchetypeType::getNew(
+ const ASTContext &Ctx,
+ ArchetypeType *Parent,
+ AssociatedTypeDecl *AssocType,
+ SmallVectorImpl<ProtocolDecl *> &ConformsTo,
+ Type Superclass) {
// Gather the set of protocol declarations to which this archetype conforms.
ProtocolType::canonicalizeProtocols(ConformsTo);
auto arena = AllocationArena::Permanent;
return CanArchetypeType(
- new (Ctx, arena) ArchetypeType(Ctx, Parent, AssocType, Name,
+ new (Ctx, arena) ArchetypeType(Ctx, Parent, AssocType,
Ctx.AllocateCopy(ConformsTo),
- Superclass, isRecursive));
+ Superclass));
+}
+
+CanArchetypeType
+ArchetypeType::getNew(const ASTContext &Ctx, Identifier Name,
+ SmallVectorImpl<ProtocolDecl *> &ConformsTo,
+ Type Superclass) {
+ // Gather the set of protocol declarations to which this archetype conforms.
+ ProtocolType::canonicalizeProtocols(ConformsTo);
+
+ auto arena = AllocationArena::Permanent;
+ return CanArchetypeType(
+ new (Ctx, arena) ArchetypeType(Ctx, nullptr, Name,
+ Ctx.AllocateCopy(ConformsTo),
+ Superclass));
}
bool ArchetypeType::requiresClass() const {
@@ -2573,37 +2566,11 @@
ArchetypeType::NestedType ArchetypeType::getNestedType(Identifier Name) const {
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
OrderArchetypeByName());
- if ((Pos == NestedTypes.end() || Pos->first != Name) && this->isRecursive) {
- if (Name == this->getName()) {
- NestedType rec = NestedType::forArchetype((ArchetypeType*)this);
-
- return rec;
- } else {
- auto conformances = this->getConformsTo();
-
- for (auto conformance : conformances) {
- auto conformanceType = conformance->getType().getPointer();
-
- if (auto metatypeType = dyn_cast<MetatypeType>(conformanceType)) {
- conformanceType = metatypeType->getInstanceType().getPointer();
-
- if (auto protocolType = dyn_cast<ProtocolType>(conformanceType)) {
- conformanceType = protocolType->getDecl()
- ->getSelfTypeInContext().getPointer();
- }
- }
-
- if (auto conformedArchetype = dyn_cast<ArchetypeType>(conformanceType)){
- return conformedArchetype->getNestedType(Name);
- }
- }
- }
- }
-
- if (Pos == NestedTypes.end() || Pos->first != Name)
+ if (Pos == NestedTypes.end() || Pos->first != Name) {
return NestedType::forConcreteType(
ErrorType::get(
const_cast<ArchetypeType *>(this)->getASTContext()));
+ }
// If the type is null, lazily resolve it.
if (!Pos->second) {
@@ -2648,6 +2615,13 @@
Archetype->getName().str().end());
}
+Identifier ArchetypeType::getName() const {
+ if (auto assocType = getAssocType())
+ return assocType->getName();
+
+ return AssocTypeOrName.get<Identifier>();
+}
+
std::string ArchetypeType::getFullName() const {
llvm::SmallString<64> Result;
collectFullName(this, Result);
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index e4b4d6d..330d623 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -814,14 +814,14 @@
}
}
- SmallVector<Type, 1> conforms_to;
- if (protocol_list.HasSingleType())
- conforms_to.push_back(protocol_list.GetFirstType());
+ SmallVector<ProtocolDecl *, 1> conforms_to;
+ if (protocol_list.HasSingleType()) {
+ (void)protocol_list.GetFirstType()->isExistentialType(conforms_to);
+ }
if (ast) {
result._types.push_back(ArchetypeType::getNew(
- *ast, nullptr, (AssociatedTypeDecl *)nullptr,
- ast->getIdentifier(archetype_name), conforms_to, Type()));
+ *ast, ast->getIdentifier(archetype_name), conforms_to, Type()));
} else {
result._error = "invalid ASTContext";
}
@@ -848,9 +848,9 @@
result._types.push_back(result_type);
else {
if (ast) {
+ SmallVector<ProtocolDecl *, 1> protocols;
result._types.push_back(ArchetypeType::getNew(
- *ast, nullptr, (AssociatedTypeDecl *)nullptr,
- ast->getIdentifier(archetype_name), ArrayRef<Type>(), Type()));
+ *ast, ast->getIdentifier(archetype_name), protocols, Type()));
} else {
result._error = "invalid ASTContext";
}
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 94e18f8..ff033ab 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -3607,14 +3607,13 @@
}
case decls_block::ARCHETYPE_TYPE: {
- IdentifierID nameID;
TypeID parentID;
- DeclID assocTypeID;
+ DeclID assocTypeOrNameID;
TypeID superclassID;
ArrayRef<uint64_t> rawConformanceIDs;
- decls_block::ArchetypeTypeLayout::readRecord(scratch, nameID, parentID,
- assocTypeID,
+ decls_block::ArchetypeTypeLayout::readRecord(scratch, parentID,
+ assocTypeOrNameID,
superclassID,
rawConformanceIDs);
@@ -3625,8 +3624,6 @@
if (auto parentType = getType(parentID))
parent = parentType->castTo<ArchetypeType>();
- auto assocTypeDecl = dyn_cast_or_null<AssociatedTypeDecl>(
- getDecl(assocTypeID));
superclass = getType(superclassID);
@@ -3637,9 +3634,16 @@
if (typeOrOffset.isComplete())
break;
- auto archetype = ArchetypeType::getNew(ctx, parent, assocTypeDecl,
- getIdentifier(nameID), conformances,
- superclass, false);
+ ArchetypeType *archetype;
+ if (parent) {
+ auto assocTypeDecl = cast<AssociatedTypeDecl>(getDecl(assocTypeOrNameID));
+ archetype = ArchetypeType::getNew(ctx, parent, assocTypeDecl,
+ conformances, superclass);
+ } else {
+ archetype = ArchetypeType::getNew(ctx, getIdentifier(assocTypeOrNameID),
+ conformances, superclass);
+ }
+
typeOrOffset = archetype;
// Read the associated type names.
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 1e8d165..6bd5e60 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2962,13 +2962,16 @@
for (auto proto : archetypeTy->getConformsTo())
conformances.push_back(addDeclRef(proto));
- DeclID assocTypeID = addDeclRef(archetypeTy->getAssocType());
+ DeclID assocTypeOrNameID;
+ if (archetypeTy->getParent())
+ assocTypeOrNameID = addDeclRef(archetypeTy->getAssocType());
+ else
+ assocTypeOrNameID = addIdentifierRef(archetypeTy->getName());
unsigned abbrCode = DeclTypeAbbrCodes[ArchetypeTypeLayout::Code];
ArchetypeTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
- addIdentifierRef(archetypeTy->getName()),
parentID,
- assocTypeID,
+ assocTypeOrNameID,
addTypeRef(archetypeTy->getSuperclass()),
conformances);