Skip to content

Commit 20a2f3e

Browse files
authored
Merge pull request #21244 from jckarter/archetype-subclasses
Split subclasses out of ArchetypeType.
2 parents fe1b75f + f1648a1 commit 20a2f3e

File tree

13 files changed

+299
-142
lines changed

13 files changed

+299
-142
lines changed

include/swift/AST/TypeNodes.def

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,13 @@ ABSTRACT_TYPE(AnyMetatype, Type)
131131
ALWAYS_CANONICAL_TYPE(Module, Type)
132132
TYPE(DynamicSelf, Type)
133133
ABSTRACT_TYPE(Substitutable, Type)
134-
ALWAYS_CANONICAL_TYPE(Archetype, SubstitutableType)
134+
ABSTRACT_TYPE(Archetype, SubstitutableType)
135+
ALWAYS_CANONICAL_TYPE(PrimaryArchetype, ArchetypeType)
136+
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
137+
ALWAYS_CANONICAL_TYPE(NestedArchetype, ArchetypeType)
138+
TYPE_RANGE(Archetype, PrimaryArchetype, NestedArchetype)
135139
TYPE(GenericTypeParam, SubstitutableType)
136-
TYPE_RANGE(Substitutable, Archetype, GenericTypeParam)
140+
TYPE_RANGE(Substitutable, PrimaryArchetype, GenericTypeParam)
137141
TYPE(DependentMember, Type)
138142
ABSTRACT_TYPE(AnyFunction, Type)
139143
TYPE(Function, AnyFunctionType)

include/swift/AST/Types.h

Lines changed: 180 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4566,17 +4566,23 @@ class SubstitutableType : public TypeBase {
45664566
};
45674567
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SubstitutableType, Type)
45684568

4569+
/// Common trailing objects for all ArchetypeType implementations, used to
4570+
/// store the constraints on the archetype.
4571+
template<typename Base, typename...AdditionalTrailingObjects>
4572+
using ArchetypeTrailingObjects = llvm::TrailingObjects<Base,
4573+
ProtocolDecl *, Type, LayoutConstraint, AdditionalTrailingObjects...>;
4574+
45694575
/// An archetype is a type that represents a runtime type that is
45704576
/// known to conform to some set of requirements.
45714577
///
45724578
/// Archetypes are used to represent generic type parameters and their
45734579
/// associated types, as well as the runtime type stored within an
45744580
/// existential container.
4575-
class ArchetypeType final : public SubstitutableType,
4576-
private llvm::TrailingObjects<ArchetypeType, ProtocolDecl *,
4577-
Type, LayoutConstraint, UUID> {
4578-
friend TrailingObjects;
4579-
4581+
class ArchetypeType : public SubstitutableType,
4582+
private llvm::trailing_objects_internal::TrailingObjectsBase
4583+
{
4584+
protected:
4585+
// Each subclass has these same trailing objects and flags.
45804586
size_t numTrailingObjects(OverloadToken<ProtocolDecl *>) const {
45814587
return Bits.ArchetypeType.NumProtocols;
45824588
}
@@ -4588,23 +4594,29 @@ class ArchetypeType final : public SubstitutableType,
45884594
size_t numTrailingObjects(OverloadToken<LayoutConstraint>) const {
45894595
return Bits.ArchetypeType.HasLayoutConstraint ? 1 : 0;
45904596
}
4591-
4592-
size_t numTrailingObjects(OverloadToken<UUID>) const {
4593-
return getOpenedExistentialType() ? 1 : 0;
4594-
}
4595-
4596-
llvm::PointerUnion3<ArchetypeType *, TypeBase *,
4597-
GenericEnvironment *> ParentOrOpenedOrEnvironment;
45984597
Type InterfaceType;
45994598
MutableArrayRef<std::pair<Identifier, Type>> NestedTypes;
46004599

46014600
void populateNestedTypes() const;
46024601
void resolveNestedType(std::pair<Identifier, Type> &nested) const;
46034602

4603+
4604+
// Helper to get the trailing objects of one of the subclasses.
4605+
template<typename Type>
4606+
const Type *getSubclassTrailingObjects() const;
4607+
4608+
template<typename Type>
4609+
Type *getSubclassTrailingObjects() {
4610+
const auto *constThis = this;
4611+
return const_cast<Type*>(constThis->getSubclassTrailingObjects<Type>());
4612+
}
4613+
46044614
public:
46054615
/// getNew - Create a new nested archetype with the given associated type.
46064616
///
46074617
/// The ConformsTo array will be copied into the ASTContext by this routine.
4618+
///
4619+
/// TODO: Move to NestedArchetypeType
46084620
static CanTypeWrapper<ArchetypeType>
46094621
getNew(const ASTContext &Ctx, ArchetypeType *Parent,
46104622
DependentMemberType *InterfaceType,
@@ -4615,6 +4627,8 @@ class ArchetypeType final : public SubstitutableType,
46154627
///
46164628
/// The ConformsTo array will be minimized then copied into the ASTContext
46174629
/// by this routine.
4630+
///
4631+
/// TODO: Move to PrimaryArchetypeType
46184632
static CanTypeWrapper<ArchetypeType>
46194633
getNew(const ASTContext &Ctx,
46204634
GenericEnvironment *GenericEnv,
@@ -4630,7 +4644,7 @@ class ArchetypeType final : public SubstitutableType,
46304644
/// \param knownID When non-empty, the known ID of the archetype. When empty,
46314645
/// a fresh archetype with a unique ID will be opened.
46324646
static CanTypeWrapper<ArchetypeType>
4633-
getOpened(Type existential,
4647+
getOpened(Type existential,
46344648
Optional<UUID> knownID = None);
46354649

46364650
/// Create a new archetype that represents the opened type
@@ -4648,18 +4662,17 @@ class ArchetypeType final : public SubstitutableType,
46484662

46494663
/// Retrieve the parent of this archetype, or null if this is a
46504664
/// primary archetype.
4651-
ArchetypeType *getParent() const {
4652-
return ParentOrOpenedOrEnvironment.dyn_cast<ArchetypeType *>();
4653-
}
4654-
4655-
/// Retrieve the opened existential type
4656-
Type getOpenedExistentialType() const {
4657-
return ParentOrOpenedOrEnvironment.dyn_cast<TypeBase *>();
4658-
}
4665+
ArchetypeType *getParent() const;
4666+
4667+
/// Retrieve the opened existential type.
4668+
/// TODO: Remove and leave on only OpenedArchetypeType
4669+
Type getOpenedExistentialType() const;
46594670

46604671
/// Retrieve the generic environment in which this archetype resides.
46614672
///
46624673
/// Note: opened archetypes currently don't have generic environments.
4674+
///
4675+
/// TODO: Remove and leave only on PrimaryArchetypeType
46634676
GenericEnvironment *getGenericEnvironment() const;
46644677

46654678
/// Retrieve the interface type of this associated type, which will either
@@ -4677,7 +4690,7 @@ class ArchetypeType final : public SubstitutableType,
46774690
/// getConformsTo - Retrieve the set of protocols to which this substitutable
46784691
/// type shall conform.
46794692
ArrayRef<ProtocolDecl *> getConformsTo() const {
4680-
return { getTrailingObjects<ProtocolDecl *>(),
4693+
return { getSubclassTrailingObjects<ProtocolDecl *>(),
46814694
static_cast<size_t>(Bits.ArchetypeType.NumProtocols) };
46824695
}
46834696

@@ -4690,14 +4703,14 @@ class ArchetypeType final : public SubstitutableType,
46904703
Type getSuperclass() const {
46914704
if (!Bits.ArchetypeType.HasSuperclass) return Type();
46924705

4693-
return *getTrailingObjects<Type>();
4706+
return *getSubclassTrailingObjects<Type>();
46944707
}
46954708

46964709
/// Retrieve the layout constraint of this type, if such a requirement exists.
46974710
LayoutConstraint getLayoutConstraint() const {
46984711
if (!Bits.ArchetypeType.HasLayoutConstraint) return LayoutConstraint();
46994712

4700-
return *getTrailingObjects<LayoutConstraint>();
4713+
return *getSubclassTrailingObjects<LayoutConstraint>();
47014714
}
47024715

47034716
/// Return true if the archetype has any requirements at all.
@@ -4749,51 +4762,159 @@ class ArchetypeType final : public SubstitutableType,
47494762
/// isPrimary - Determine whether this is the archetype for a 'primary'
47504763
/// archetype, e.g., one that is not nested within another archetype and is
47514764
/// not an opened existential.
4752-
bool isPrimary() const {
4753-
return ParentOrOpenedOrEnvironment.is<GenericEnvironment *>();
4754-
}
4765+
bool isPrimary() const;
47554766

47564767
/// getPrimary - Return the primary archetype parent of this archetype.
4757-
ArchetypeType *getPrimary() const {
4758-
assert(!getOpenedExistentialType() && "Check for opened existential first");
4759-
4760-
auto *archetype = this;
4761-
while (auto *parent = archetype->getParent())
4762-
archetype = parent;
4763-
return const_cast<ArchetypeType *>(archetype);
4764-
}
4768+
ArchetypeType *getPrimary() const;
47654769

47664770
/// Retrieve the ID number of this opened existential.
4767-
UUID getOpenedExistentialID() const {
4768-
assert(getOpenedExistentialType() && "Not an opened existential archetype");
4769-
// The UUID is tail-allocated at the end of opened existential archetypes.
4770-
return *getTrailingObjects<UUID>();
4771-
}
4771+
///
4772+
/// TODO: Remove and place on OpenedArchetypeType only
4773+
UUID getOpenedExistentialID() const;
47724774

47734775
// Implement isa/cast/dyncast/etc.
47744776
static bool classof(const TypeBase *T) {
4775-
return T->getKind() == TypeKind::Archetype;
4777+
return T->getKind() >= TypeKind::First_ArchetypeType
4778+
&& T->getKind() <= TypeKind::Last_ArchetypeType;
47764779
}
4777-
4778-
private:
4779-
ArchetypeType(
4780-
const ASTContext &Ctx,
4781-
llvm::PointerUnion<ArchetypeType *, GenericEnvironment *>
4782-
ParentOrGenericEnv,
4783-
Type InterfaceType,
4784-
ArrayRef<ProtocolDecl *> ConformsTo,
4785-
Type Superclass, LayoutConstraint Layout);
4786-
4787-
ArchetypeType(const ASTContext &Ctx, Type Existential,
4788-
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
4789-
LayoutConstraint Layout, UUID uuid);
4780+
protected:
4781+
ArchetypeType(TypeKind Kind,
4782+
const ASTContext &C,
4783+
RecursiveTypeProperties properties,
4784+
Type InterfaceType,
4785+
ArrayRef<ProtocolDecl *> ConformsTo,
4786+
Type Superclass, LayoutConstraint Layout);
47904787
};
47914788
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
47924789
CanArchetypeType getParent() const {
47934790
return CanArchetypeType(getPointer()->getParent());
47944791
}
47954792
END_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
4793+
4794+
/// An archetype that represents a primary generic argument inside the generic
4795+
/// context that binds it.
4796+
class PrimaryArchetypeType final : public ArchetypeType,
4797+
private ArchetypeTrailingObjects<PrimaryArchetypeType>
4798+
{
4799+
friend TrailingObjects;
4800+
friend ArchetypeType;
4801+
4802+
GenericEnvironment *Environment;
4803+
4804+
public:
4805+
/// Retrieve the generic environment in which this archetype resides.
4806+
GenericEnvironment *getGenericEnvironment() const {
4807+
return Environment;
4808+
}
4809+
4810+
static bool classof(const TypeBase *T) {
4811+
return T->getKind() == TypeKind::PrimaryArchetype;
4812+
}
4813+
private:
4814+
PrimaryArchetypeType(const ASTContext &Ctx,
4815+
GenericEnvironment *GenericEnv,
4816+
Type InterfaceType,
4817+
ArrayRef<ProtocolDecl *> ConformsTo,
4818+
Type Superclass, LayoutConstraint Layout);
4819+
};
4820+
BEGIN_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
4821+
END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
4822+
4823+
/// An archetype that represents the dynamic type of an opened existential.
4824+
class OpenedArchetypeType final : public ArchetypeType,
4825+
private ArchetypeTrailingObjects<OpenedArchetypeType>
4826+
{
4827+
friend TrailingObjects;
4828+
friend ArchetypeType;
4829+
4830+
TypeBase *Opened;
4831+
UUID ID;
4832+
public:
4833+
/// Retrieve the ID number of this opened existential.
4834+
UUID getOpenedExistentialID() const { return ID; }
4835+
4836+
/// Retrieve the opened existential type
4837+
Type getOpenedExistentialType() const {
4838+
return Opened;
4839+
}
4840+
4841+
static bool classof(const TypeBase *T) {
4842+
return T->getKind() == TypeKind::OpenedArchetype;
4843+
}
4844+
4845+
private:
4846+
OpenedArchetypeType(const ASTContext &Ctx, Type Existential,
4847+
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
4848+
LayoutConstraint Layout, UUID uuid);
4849+
};
4850+
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
4851+
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
4852+
4853+
/// An archetype that is a nested associated type of another archetype.
4854+
class NestedArchetypeType final : public ArchetypeType,
4855+
private ArchetypeTrailingObjects<NestedArchetypeType>
4856+
{
4857+
friend TrailingObjects;
4858+
friend ArchetypeType;
4859+
4860+
ArchetypeType *Parent;
4861+
4862+
public:
4863+
/// Retrieve the parent of this archetype, or null if this is a
4864+
/// primary archetype.
4865+
ArchetypeType *getParent() const {
4866+
return Parent;
4867+
}
4868+
4869+
static bool classof(const TypeBase *T) {
4870+
return T->getKind() == TypeKind::NestedArchetype;
4871+
}
4872+
4873+
private:
4874+
NestedArchetypeType(const ASTContext &Ctx,
4875+
ArchetypeType *Parent,
4876+
Type InterfaceType,
4877+
ArrayRef<ProtocolDecl *> ConformsTo,
4878+
Type Superclass, LayoutConstraint Layout);
4879+
};
4880+
BEGIN_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)
4881+
END_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)
47964882

4883+
inline bool ArchetypeType::isPrimary() const {
4884+
return isa<PrimaryArchetypeType>(this);
4885+
}
4886+
4887+
inline UUID ArchetypeType::getOpenedExistentialID() const {
4888+
return cast<OpenedArchetypeType>(this)->getOpenedExistentialID();
4889+
}
4890+
4891+
inline Type ArchetypeType::getOpenedExistentialType() const {
4892+
if (auto child = dyn_cast<OpenedArchetypeType>(this))
4893+
return child->getOpenedExistentialType();
4894+
return nullptr;
4895+
}
4896+
4897+
inline ArchetypeType *ArchetypeType::getParent() const {
4898+
if (auto child = dyn_cast<NestedArchetypeType>(this))
4899+
return child->getParent();
4900+
4901+
return nullptr;
4902+
}
4903+
4904+
template<typename Type>
4905+
const Type *ArchetypeType::getSubclassTrailingObjects() const {
4906+
if (auto contextTy = dyn_cast<PrimaryArchetypeType>(this)) {
4907+
return contextTy->getTrailingObjects<Type>();
4908+
}
4909+
if (auto openedTy = dyn_cast<OpenedArchetypeType>(this)) {
4910+
return openedTy->getTrailingObjects<Type>();
4911+
}
4912+
if (auto childTy = dyn_cast<NestedArchetypeType>(this)) {
4913+
return childTy->getTrailingObjects<Type>();
4914+
}
4915+
llvm_unreachable("unhandled ArchetypeType subclass?");
4916+
}
4917+
47974918
/// Describes the type of a generic parameter.
47984919
///
47994920
/// \sa GenericTypeParamDecl
@@ -5391,8 +5512,11 @@ inline bool TypeBase::hasSimpleTypeRepr() const {
53915512
case TypeKind::ExistentialMetatype:
53925513
return !cast<const AnyMetatypeType>(this)->hasRepresentation();
53935514

5394-
case TypeKind::Archetype:
5395-
return !cast<const ArchetypeType>(this)->isOpenedExistential();
5515+
case TypeKind::NestedArchetype:
5516+
return cast<NestedArchetypeType>(this)->getParent()->hasSimpleTypeRepr();
5517+
5518+
case TypeKind::OpenedArchetype:
5519+
return false;
53965520

53975521
case TypeKind::ProtocolComposition: {
53985522
// 'Any', 'AnyObject' and single protocol compositions are simple

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4301,15 +4301,14 @@ CanArchetypeType ArchetypeType::getOpened(Type existential,
43014301

43024302
auto arena = AllocationArena::Permanent;
43034303
void *mem = ctx.Allocate(
4304-
totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint, UUID>(
4304+
OpenedArchetypeType::totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint>(
43054305
protos.size(),
43064306
layoutSuperclass ? 1 : 0,
4307-
layoutConstraint ? 1 : 0, 1),
4308-
alignof(ArchetypeType), arena);
4307+
layoutConstraint ? 1 : 0),
4308+
alignof(OpenedArchetypeType), arena);
43094309

4310-
// FIXME: Pass in class layout constraint
43114310
auto result =
4312-
::new (mem) ArchetypeType(ctx, existential,
4311+
::new (mem) OpenedArchetypeType(ctx, existential,
43134312
protos, layoutSuperclass,
43144313
layoutConstraint, *knownID);
43154314
openedExistentialArchetypes[*knownID] = result;

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,9 @@ void ASTMangler::appendType(Type type) {
866866
return appendImplFunctionType(cast<SILFunctionType>(tybase));
867867

868868
// type ::= archetype
869-
case TypeKind::Archetype:
869+
case TypeKind::PrimaryArchetype:
870+
case TypeKind::OpenedArchetype:
871+
case TypeKind::NestedArchetype:
870872
llvm_unreachable("Cannot mangle free-standing archetypes");
871873

872874
case TypeKind::DynamicSelf: {

0 commit comments

Comments
 (0)