Skip to content

Split subclasses out of ArchetypeType. #21244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions include/swift/AST/TypeNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,13 @@ ABSTRACT_TYPE(AnyMetatype, Type)
ALWAYS_CANONICAL_TYPE(Module, Type)
TYPE(DynamicSelf, Type)
ABSTRACT_TYPE(Substitutable, Type)
ALWAYS_CANONICAL_TYPE(Archetype, SubstitutableType)
ABSTRACT_TYPE(Archetype, SubstitutableType)
ALWAYS_CANONICAL_TYPE(PrimaryArchetype, ArchetypeType)
ALWAYS_CANONICAL_TYPE(OpenedArchetype, ArchetypeType)
ALWAYS_CANONICAL_TYPE(NestedArchetype, ArchetypeType)
TYPE_RANGE(Archetype, PrimaryArchetype, NestedArchetype)
TYPE(GenericTypeParam, SubstitutableType)
TYPE_RANGE(Substitutable, Archetype, GenericTypeParam)
TYPE_RANGE(Substitutable, PrimaryArchetype, GenericTypeParam)
TYPE(DependentMember, Type)
ABSTRACT_TYPE(AnyFunction, Type)
TYPE(Function, AnyFunctionType)
Expand Down
236 changes: 180 additions & 56 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4566,17 +4566,23 @@ class SubstitutableType : public TypeBase {
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SubstitutableType, Type)

/// Common trailing objects for all ArchetypeType implementations, used to
/// store the constraints on the archetype.
template<typename Base, typename...AdditionalTrailingObjects>
using ArchetypeTrailingObjects = llvm::TrailingObjects<Base,
ProtocolDecl *, Type, LayoutConstraint, AdditionalTrailingObjects...>;

/// An archetype is a type that represents a runtime type that is
/// known to conform to some set of requirements.
///
/// Archetypes are used to represent generic type parameters and their
/// associated types, as well as the runtime type stored within an
/// existential container.
class ArchetypeType final : public SubstitutableType,
private llvm::TrailingObjects<ArchetypeType, ProtocolDecl *,
Type, LayoutConstraint, UUID> {
friend TrailingObjects;

class ArchetypeType : public SubstitutableType,
private llvm::trailing_objects_internal::TrailingObjectsBase
{
protected:
// Each subclass has these same trailing objects and flags.
size_t numTrailingObjects(OverloadToken<ProtocolDecl *>) const {
return Bits.ArchetypeType.NumProtocols;
}
Expand All @@ -4588,23 +4594,29 @@ class ArchetypeType final : public SubstitutableType,
size_t numTrailingObjects(OverloadToken<LayoutConstraint>) const {
return Bits.ArchetypeType.HasLayoutConstraint ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<UUID>) const {
return getOpenedExistentialType() ? 1 : 0;
}

llvm::PointerUnion3<ArchetypeType *, TypeBase *,
GenericEnvironment *> ParentOrOpenedOrEnvironment;
Type InterfaceType;
MutableArrayRef<std::pair<Identifier, Type>> NestedTypes;

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


// Helper to get the trailing objects of one of the subclasses.
template<typename Type>
const Type *getSubclassTrailingObjects() const;

template<typename Type>
Type *getSubclassTrailingObjects() {
const auto *constThis = this;
return const_cast<Type*>(constThis->getSubclassTrailingObjects<Type>());
}

public:
/// getNew - Create a new nested archetype with the given associated type.
///
/// The ConformsTo array will be copied into the ASTContext by this routine.
///
/// TODO: Move to NestedArchetypeType
static CanTypeWrapper<ArchetypeType>
getNew(const ASTContext &Ctx, ArchetypeType *Parent,
DependentMemberType *InterfaceType,
Expand All @@ -4615,6 +4627,8 @@ class ArchetypeType final : public SubstitutableType,
///
/// The ConformsTo array will be minimized then copied into the ASTContext
/// by this routine.
///
/// TODO: Move to PrimaryArchetypeType
static CanTypeWrapper<ArchetypeType>
getNew(const ASTContext &Ctx,
GenericEnvironment *GenericEnv,
Expand All @@ -4630,7 +4644,7 @@ class ArchetypeType final : public SubstitutableType,
/// \param knownID When non-empty, the known ID of the archetype. When empty,
/// a fresh archetype with a unique ID will be opened.
static CanTypeWrapper<ArchetypeType>
getOpened(Type existential,
getOpened(Type existential,
Optional<UUID> knownID = None);

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

/// Retrieve the parent of this archetype, or null if this is a
/// primary archetype.
ArchetypeType *getParent() const {
return ParentOrOpenedOrEnvironment.dyn_cast<ArchetypeType *>();
}

/// Retrieve the opened existential type
Type getOpenedExistentialType() const {
return ParentOrOpenedOrEnvironment.dyn_cast<TypeBase *>();
}
ArchetypeType *getParent() const;

/// Retrieve the opened existential type.
/// TODO: Remove and leave on only OpenedArchetypeType
Type getOpenedExistentialType() const;

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

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

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

return *getTrailingObjects<Type>();
return *getSubclassTrailingObjects<Type>();
}

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

return *getTrailingObjects<LayoutConstraint>();
return *getSubclassTrailingObjects<LayoutConstraint>();
}

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

/// getPrimary - Return the primary archetype parent of this archetype.
ArchetypeType *getPrimary() const {
assert(!getOpenedExistentialType() && "Check for opened existential first");

auto *archetype = this;
while (auto *parent = archetype->getParent())
archetype = parent;
return const_cast<ArchetypeType *>(archetype);
}
ArchetypeType *getPrimary() const;

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

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::Archetype;
return T->getKind() >= TypeKind::First_ArchetypeType
&& T->getKind() <= TypeKind::Last_ArchetypeType;
}

private:
ArchetypeType(
const ASTContext &Ctx,
llvm::PointerUnion<ArchetypeType *, GenericEnvironment *>
ParentOrGenericEnv,
Type InterfaceType,
ArrayRef<ProtocolDecl *> ConformsTo,
Type Superclass, LayoutConstraint Layout);

ArchetypeType(const ASTContext &Ctx, Type Existential,
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
LayoutConstraint Layout, UUID uuid);
protected:
ArchetypeType(TypeKind Kind,
const ASTContext &C,
RecursiveTypeProperties properties,
Type InterfaceType,
ArrayRef<ProtocolDecl *> ConformsTo,
Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
CanArchetypeType getParent() const {
return CanArchetypeType(getPointer()->getParent());
}
END_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)

/// An archetype that represents a primary generic argument inside the generic
/// context that binds it.
class PrimaryArchetypeType final : public ArchetypeType,
private ArchetypeTrailingObjects<PrimaryArchetypeType>
{
friend TrailingObjects;
friend ArchetypeType;

GenericEnvironment *Environment;

public:
/// Retrieve the generic environment in which this archetype resides.
GenericEnvironment *getGenericEnvironment() const {
return Environment;
}

static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::PrimaryArchetype;
}
private:
PrimaryArchetypeType(const ASTContext &Ctx,
GenericEnvironment *GenericEnv,
Type InterfaceType,
ArrayRef<ProtocolDecl *> ConformsTo,
Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)

/// An archetype that represents the dynamic type of an opened existential.
class OpenedArchetypeType final : public ArchetypeType,
private ArchetypeTrailingObjects<OpenedArchetypeType>
{
friend TrailingObjects;
friend ArchetypeType;

TypeBase *Opened;
UUID ID;
public:
/// Retrieve the ID number of this opened existential.
UUID getOpenedExistentialID() const { return ID; }

/// Retrieve the opened existential type
Type getOpenedExistentialType() const {
return Opened;
}

static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::OpenedArchetype;
}

private:
OpenedArchetypeType(const ASTContext &Ctx, Type Existential,
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,
LayoutConstraint Layout, UUID uuid);
};
BEGIN_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(OpenedArchetypeType, ArchetypeType)

/// An archetype that is a nested associated type of another archetype.
class NestedArchetypeType final : public ArchetypeType,
private ArchetypeTrailingObjects<NestedArchetypeType>
{
friend TrailingObjects;
friend ArchetypeType;

ArchetypeType *Parent;

public:
/// Retrieve the parent of this archetype, or null if this is a
/// primary archetype.
ArchetypeType *getParent() const {
return Parent;
}

static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::NestedArchetype;
}

private:
NestedArchetypeType(const ASTContext &Ctx,
ArchetypeType *Parent,
Type InterfaceType,
ArrayRef<ProtocolDecl *> ConformsTo,
Type Superclass, LayoutConstraint Layout);
};
BEGIN_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)
END_CAN_TYPE_WRAPPER(NestedArchetypeType, ArchetypeType)

inline bool ArchetypeType::isPrimary() const {
return isa<PrimaryArchetypeType>(this);
}

inline UUID ArchetypeType::getOpenedExistentialID() const {
return cast<OpenedArchetypeType>(this)->getOpenedExistentialID();
}

inline Type ArchetypeType::getOpenedExistentialType() const {
if (auto child = dyn_cast<OpenedArchetypeType>(this))
return child->getOpenedExistentialType();
return nullptr;
}

inline ArchetypeType *ArchetypeType::getParent() const {
if (auto child = dyn_cast<NestedArchetypeType>(this))
return child->getParent();

return nullptr;
}

template<typename Type>
const Type *ArchetypeType::getSubclassTrailingObjects() const {
if (auto contextTy = dyn_cast<PrimaryArchetypeType>(this)) {
return contextTy->getTrailingObjects<Type>();
}
if (auto openedTy = dyn_cast<OpenedArchetypeType>(this)) {
return openedTy->getTrailingObjects<Type>();
}
if (auto childTy = dyn_cast<NestedArchetypeType>(this)) {
return childTy->getTrailingObjects<Type>();
}
llvm_unreachable("unhandled ArchetypeType subclass?");
}

/// Describes the type of a generic parameter.
///
/// \sa GenericTypeParamDecl
Expand Down Expand Up @@ -5391,8 +5512,11 @@ inline bool TypeBase::hasSimpleTypeRepr() const {
case TypeKind::ExistentialMetatype:
return !cast<const AnyMetatypeType>(this)->hasRepresentation();

case TypeKind::Archetype:
return !cast<const ArchetypeType>(this)->isOpenedExistential();
case TypeKind::NestedArchetype:
return cast<NestedArchetypeType>(this)->getParent()->hasSimpleTypeRepr();

case TypeKind::OpenedArchetype:
return false;

case TypeKind::ProtocolComposition: {
// 'Any', 'AnyObject' and single protocol compositions are simple
Expand Down
9 changes: 4 additions & 5 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4301,15 +4301,14 @@ CanArchetypeType ArchetypeType::getOpened(Type existential,

auto arena = AllocationArena::Permanent;
void *mem = ctx.Allocate(
totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint, UUID>(
OpenedArchetypeType::totalSizeToAlloc<ProtocolDecl *, Type, LayoutConstraint>(
protos.size(),
layoutSuperclass ? 1 : 0,
layoutConstraint ? 1 : 0, 1),
alignof(ArchetypeType), arena);
layoutConstraint ? 1 : 0),
alignof(OpenedArchetypeType), arena);

// FIXME: Pass in class layout constraint
auto result =
::new (mem) ArchetypeType(ctx, existential,
::new (mem) OpenedArchetypeType(ctx, existential,
protos, layoutSuperclass,
layoutConstraint, *knownID);
openedExistentialArchetypes[*knownID] = result;
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,9 @@ void ASTMangler::appendType(Type type) {
return appendImplFunctionType(cast<SILFunctionType>(tybase));

// type ::= archetype
case TypeKind::Archetype:
case TypeKind::PrimaryArchetype:
case TypeKind::OpenedArchetype:
case TypeKind::NestedArchetype:
llvm_unreachable("Cannot mangle free-standing archetypes");

case TypeKind::DynamicSelf: {
Expand Down
Loading