mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Archetype builder] Separate potential archetypes from *specific* archetypes.
Stop recording specific archetypes anywhere in PotentialArchetype. Instead, use a GenericEnvironment to record/query the archetype that corresponds to that PotentialArchetype, making it possible to use the same archetype builder (and its potential archetypes) to build multiple generic environments.
This commit is contained in:
@@ -366,9 +366,9 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
llvm::MapVector<Identifier, llvm::TinyPtrVector<PotentialArchetype *>>
|
llvm::MapVector<Identifier, llvm::TinyPtrVector<PotentialArchetype *>>
|
||||||
NestedTypes;
|
NestedTypes;
|
||||||
|
|
||||||
/// \brief The actual archetype, once it has been assigned, or the concrete
|
/// The concrete type to which a this potential archetype has been
|
||||||
/// type that the parameter was same-type constrained to.
|
/// constrained.
|
||||||
ArchetypeType::NestedType ArchetypeOrConcreteType;
|
Type ConcreteType;
|
||||||
|
|
||||||
/// \brief Recursively conforms to itself.
|
/// \brief Recursively conforms to itself.
|
||||||
unsigned IsRecursive : 1;
|
unsigned IsRecursive : 1;
|
||||||
@@ -377,10 +377,6 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
/// be resolved.
|
/// be resolved.
|
||||||
unsigned Invalid : 1;
|
unsigned Invalid : 1;
|
||||||
|
|
||||||
/// Whether we are currently substituting into the concrete type of
|
|
||||||
/// this potential archetype.
|
|
||||||
unsigned SubstitutingConcreteType : 1;
|
|
||||||
|
|
||||||
/// Whether we have detected recursion during the substitution of
|
/// Whether we have detected recursion during the substitution of
|
||||||
/// the concrete type.
|
/// the concrete type.
|
||||||
unsigned RecursiveConcreteType : 1;
|
unsigned RecursiveConcreteType : 1;
|
||||||
@@ -403,7 +399,7 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
/// associated type.
|
/// associated type.
|
||||||
PotentialArchetype(PotentialArchetype *Parent, Identifier Name)
|
PotentialArchetype(PotentialArchetype *Parent, Identifier Name)
|
||||||
: ParentOrParam(Parent), NameOrAssociatedType(Name), Representative(this),
|
: ParentOrParam(Parent), NameOrAssociatedType(Name), Representative(this),
|
||||||
IsRecursive(false), Invalid(false), SubstitutingConcreteType(false),
|
IsRecursive(false), Invalid(false),
|
||||||
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
||||||
DiagnosedRename(false)
|
DiagnosedRename(false)
|
||||||
{
|
{
|
||||||
@@ -415,7 +411,7 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
PotentialArchetype(PotentialArchetype *Parent, AssociatedTypeDecl *AssocType)
|
PotentialArchetype(PotentialArchetype *Parent, AssociatedTypeDecl *AssocType)
|
||||||
: ParentOrParam(Parent), NameOrAssociatedType(AssocType),
|
: ParentOrParam(Parent), NameOrAssociatedType(AssocType),
|
||||||
Representative(this), IsRecursive(false), Invalid(false),
|
Representative(this), IsRecursive(false), Invalid(false),
|
||||||
SubstitutingConcreteType(false), RecursiveConcreteType(false),
|
RecursiveConcreteType(false),
|
||||||
RecursiveSuperclassType(false), DiagnosedRename(false)
|
RecursiveSuperclassType(false), DiagnosedRename(false)
|
||||||
{
|
{
|
||||||
assert(Parent != nullptr && "Not an associated type?");
|
assert(Parent != nullptr && "Not an associated type?");
|
||||||
@@ -426,7 +422,7 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
PotentialArchetype(PotentialArchetype *Parent, TypeAliasDecl *TypeAlias)
|
PotentialArchetype(PotentialArchetype *Parent, TypeAliasDecl *TypeAlias)
|
||||||
: ParentOrParam(Parent), NameOrAssociatedType(TypeAlias),
|
: ParentOrParam(Parent), NameOrAssociatedType(TypeAlias),
|
||||||
Representative(this), IsRecursive(false), Invalid(false),
|
Representative(this), IsRecursive(false), Invalid(false),
|
||||||
SubstitutingConcreteType(false), RecursiveConcreteType(false),
|
RecursiveConcreteType(false),
|
||||||
RecursiveSuperclassType(false), DiagnosedRename(false)
|
RecursiveSuperclassType(false), DiagnosedRename(false)
|
||||||
{
|
{
|
||||||
assert(Parent != nullptr && "Not an associated type?");
|
assert(Parent != nullptr && "Not an associated type?");
|
||||||
@@ -438,7 +434,7 @@ class ArchetypeBuilder::PotentialArchetype {
|
|||||||
Identifier Name)
|
Identifier Name)
|
||||||
: ParentOrParam(GenericParam),
|
: ParentOrParam(GenericParam),
|
||||||
NameOrAssociatedType(Name), Representative(this), IsRecursive(false),
|
NameOrAssociatedType(Name), Representative(this), IsRecursive(false),
|
||||||
Invalid(false), SubstitutingConcreteType(false),
|
Invalid(false),
|
||||||
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
RecursiveConcreteType(false), RecursiveSuperclassType(false),
|
||||||
DiagnosedRename(false)
|
DiagnosedRename(false)
|
||||||
{
|
{
|
||||||
@@ -550,9 +546,11 @@ public:
|
|||||||
PotentialArchetype *getNestedType(Identifier Name,
|
PotentialArchetype *getNestedType(Identifier Name,
|
||||||
ArchetypeBuilder &builder);
|
ArchetypeBuilder &builder);
|
||||||
|
|
||||||
|
|
||||||
/// \brief Retrieve (or build) the type corresponding to the potential
|
/// \brief Retrieve (or build) the type corresponding to the potential
|
||||||
/// archetype.
|
/// archetype within the given generic environment.
|
||||||
ArchetypeType::NestedType getType(ArchetypeBuilder &builder);
|
ArchetypeType::NestedType getTypeInContext(ArchetypeBuilder &builder,
|
||||||
|
GenericEnvironment *genericEnv);
|
||||||
|
|
||||||
/// Retrieve the dependent type that describes this potential
|
/// Retrieve the dependent type that describes this potential
|
||||||
/// archetype.
|
/// archetype.
|
||||||
@@ -568,15 +566,14 @@ public:
|
|||||||
if (Representative != this)
|
if (Representative != this)
|
||||||
return Representative->isConcreteType();
|
return Representative->isConcreteType();
|
||||||
|
|
||||||
return ArchetypeOrConcreteType.isConcreteType();
|
return static_cast<bool>(ConcreteType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the concrete type this potential archetype is constrained to.
|
/// Get the concrete type this potential archetype is constrained to.
|
||||||
Type getConcreteType() const {
|
Type getConcreteType() const {
|
||||||
assert(isConcreteType());
|
|
||||||
if (Representative != this)
|
if (Representative != this)
|
||||||
return Representative->getConcreteType();
|
return Representative->getConcreteType();
|
||||||
return ArchetypeOrConcreteType.getAsConcreteType();
|
return ConcreteType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIsRecursive() { IsRecursive = true; }
|
void setIsRecursive() { IsRecursive = true; }
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
|
class ArchetypeBuilder;
|
||||||
class ASTContext;
|
class ASTContext;
|
||||||
class GenericTypeParamType;
|
class GenericTypeParamType;
|
||||||
class SILModule;
|
class SILModule;
|
||||||
@@ -29,7 +30,7 @@ class SILType;
|
|||||||
|
|
||||||
/// Describes the mapping between archetypes and interface types for the
|
/// Describes the mapping between archetypes and interface types for the
|
||||||
/// generic parameters of a DeclContext.
|
/// generic parameters of a DeclContext.
|
||||||
class GenericEnvironment final {
|
class alignas(1 << DeclAlignInBits) GenericEnvironment final {
|
||||||
GenericSignature *Signature;
|
GenericSignature *Signature;
|
||||||
TypeSubstitutionMap ArchetypeToInterfaceMap;
|
TypeSubstitutionMap ArchetypeToInterfaceMap;
|
||||||
TypeSubstitutionMap InterfaceToArchetypeMap;
|
TypeSubstitutionMap InterfaceToArchetypeMap;
|
||||||
@@ -65,6 +66,11 @@ public:
|
|||||||
/// an archetype)
|
/// an archetype)
|
||||||
void addMapping(GenericTypeParamType *genericParam, Type contextType);
|
void addMapping(GenericTypeParamType *genericParam, Type contextType);
|
||||||
|
|
||||||
|
/// Retrieve the mapping for the given generic parameter, if present.
|
||||||
|
///
|
||||||
|
/// This is only useful when lazily populating a generic environment.
|
||||||
|
Optional<Type> getMappingIfPresent(GenericTypeParamType *genericParam) const;
|
||||||
|
|
||||||
/// Make vanilla new/delete illegal.
|
/// Make vanilla new/delete illegal.
|
||||||
void *operator new(size_t Bytes) = delete;
|
void *operator new(size_t Bytes) = delete;
|
||||||
void operator delete(void *Data) = delete;
|
void operator delete(void *Data) = delete;
|
||||||
@@ -80,9 +86,6 @@ public:
|
|||||||
Type mapTypeIntoContext(ModuleDecl *M, Type type) const;
|
Type mapTypeIntoContext(ModuleDecl *M, Type type) const;
|
||||||
|
|
||||||
/// Map a generic parameter type to a contextual type.
|
/// Map a generic parameter type to a contextual type.
|
||||||
///
|
|
||||||
/// This operation will also reabstract dependent types according to the
|
|
||||||
/// abstraction level of their associated type requirements.
|
|
||||||
Type mapTypeIntoContext(GenericTypeParamType *type) const;
|
Type mapTypeIntoContext(GenericTypeParamType *type) const;
|
||||||
|
|
||||||
/// \brief Map the given SIL interface type to a contextual type.
|
/// \brief Map the given SIL interface type to a contextual type.
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace swift {
|
|||||||
class DeclContext;
|
class DeclContext;
|
||||||
class Expr;
|
class Expr;
|
||||||
class ExtensionDecl;
|
class ExtensionDecl;
|
||||||
|
class GenericEnvironment;
|
||||||
class GenericTypeParamDecl;
|
class GenericTypeParamDecl;
|
||||||
class NormalProtocolConformance;
|
class NormalProtocolConformance;
|
||||||
class OperatorDecl;
|
class OperatorDecl;
|
||||||
@@ -97,6 +98,8 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::Expr, swift::ExprAlignInBits)
|
|||||||
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolConformance, swift::DeclAlignInBits)
|
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ProtocolConformance, swift::DeclAlignInBits)
|
||||||
LLVM_DECLARE_TYPE_ALIGNMENT(swift::NormalProtocolConformance,
|
LLVM_DECLARE_TYPE_ALIGNMENT(swift::NormalProtocolConformance,
|
||||||
swift::DeclAlignInBits)
|
swift::DeclAlignInBits)
|
||||||
|
LLVM_DECLARE_TYPE_ALIGNMENT(swift::GenericEnvironment,
|
||||||
|
swift::DeclAlignInBits)
|
||||||
|
|
||||||
static_assert(llvm::AlignOf<void*>::Alignment >= 2,
|
static_assert(llvm::AlignOf<void*>::Alignment >= 2,
|
||||||
"pointer alignment is too small");
|
"pointer alignment is too small");
|
||||||
|
|||||||
@@ -3776,7 +3776,8 @@ private:
|
|||||||
ArrayRef<ProtocolDecl *> ConformsTo;
|
ArrayRef<ProtocolDecl *> ConformsTo;
|
||||||
Type Superclass;
|
Type Superclass;
|
||||||
|
|
||||||
llvm::PointerUnion<ArchetypeType *, TypeBase *> ParentOrOpened;
|
llvm::PointerUnion3<ArchetypeType *, TypeBase *,
|
||||||
|
GenericEnvironment *> ParentOrOpenedOrEnvironment;
|
||||||
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName;
|
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName;
|
||||||
MutableArrayRef<std::pair<Identifier, NestedType>> NestedTypes;
|
MutableArrayRef<std::pair<Identifier, NestedType>> NestedTypes;
|
||||||
|
|
||||||
@@ -3790,7 +3791,7 @@ private:
|
|||||||
void resolveNestedType(std::pair<Identifier, NestedType> &nested) const;
|
void resolveNestedType(std::pair<Identifier, NestedType> &nested) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// getNew - Create a new archetype with the given name.
|
/// getNew - Create a new nested archetype with the given associated type.
|
||||||
///
|
///
|
||||||
/// The ConformsTo array will be copied into the ASTContext by this routine.
|
/// The ConformsTo array will be copied into the ASTContext by this routine.
|
||||||
static CanTypeWrapper<ArchetypeType>
|
static CanTypeWrapper<ArchetypeType>
|
||||||
@@ -3799,12 +3800,13 @@ public:
|
|||||||
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
||||||
Type Superclass);
|
Type Superclass);
|
||||||
|
|
||||||
/// getNew - Create a new archetype with the given name.
|
/// getNew - Create a new primary archetype with the given name.
|
||||||
///
|
///
|
||||||
/// The ConformsTo array will be minimized then copied into the ASTContext
|
/// The ConformsTo array will be minimized then copied into the ASTContext
|
||||||
/// by this routine.
|
/// by this routine.
|
||||||
static CanTypeWrapper<ArchetypeType>
|
static CanTypeWrapper<ArchetypeType>
|
||||||
getNew(const ASTContext &Ctx,
|
getNew(const ASTContext &Ctx,
|
||||||
|
GenericEnvironment *genericEnvironment,
|
||||||
Identifier Name,
|
Identifier Name,
|
||||||
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
||||||
Type Superclass);
|
Type Superclass);
|
||||||
@@ -3836,14 +3838,19 @@ public:
|
|||||||
/// \brief Retrieve the parent of this archetype, or null if this is a
|
/// \brief Retrieve the parent of this archetype, or null if this is a
|
||||||
/// primary archetype.
|
/// primary archetype.
|
||||||
ArchetypeType *getParent() const {
|
ArchetypeType *getParent() const {
|
||||||
return ParentOrOpened.dyn_cast<ArchetypeType *>();
|
return ParentOrOpenedOrEnvironment.dyn_cast<ArchetypeType *>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the opened existential type
|
/// Retrieve the opened existential type
|
||||||
Type getOpenedExistentialType() const {
|
Type getOpenedExistentialType() const {
|
||||||
return ParentOrOpened.dyn_cast<TypeBase *>();
|
return ParentOrOpenedOrEnvironment.dyn_cast<TypeBase *>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve the generic environment in which this archetype resides.
|
||||||
|
///
|
||||||
|
/// FIXME: Not all archetypes have generic environments, yet.
|
||||||
|
GenericEnvironment *getGenericEnvironment() const;
|
||||||
|
|
||||||
/// Retrieve the associated type to which this archetype (if it is a nested
|
/// Retrieve the associated type to which this archetype (if it is a nested
|
||||||
/// archetype) corresponds.
|
/// archetype) corresponds.
|
||||||
///
|
///
|
||||||
@@ -3866,6 +3873,12 @@ public:
|
|||||||
/// \brief Retrieve the superclass of this type, if such a requirement exists.
|
/// \brief Retrieve the superclass of this type, if such a requirement exists.
|
||||||
Type getSuperclass() const { return Superclass; }
|
Type getSuperclass() const { return Superclass; }
|
||||||
|
|
||||||
|
/// \brief Set the superclass of this type.
|
||||||
|
///
|
||||||
|
/// This can only be performed in very narrow cases where the archetype is
|
||||||
|
/// being lazily constructed.
|
||||||
|
void setSuperclass(Type superclass) { Superclass = superclass; }
|
||||||
|
|
||||||
/// \brief Return true if the archetype has any requirements at all.
|
/// \brief Return true if the archetype has any requirements at all.
|
||||||
bool hasRequirements() const {
|
bool hasRequirements() const {
|
||||||
return !getConformsTo().empty() || getSuperclass();
|
return !getConformsTo().empty() || getSuperclass();
|
||||||
@@ -3874,6 +3887,12 @@ public:
|
|||||||
/// \brief Retrieve the nested type with the given name.
|
/// \brief Retrieve the nested type with the given name.
|
||||||
NestedType getNestedType(Identifier Name) const;
|
NestedType getNestedType(Identifier Name) const;
|
||||||
|
|
||||||
|
/// \brief Retrieve the nested type with the given name, if it's already
|
||||||
|
/// known.
|
||||||
|
///
|
||||||
|
/// This is an implementation detail used by the archetype builder.
|
||||||
|
Optional<NestedType> getNestedTypeIfKnown(Identifier Name) const;
|
||||||
|
|
||||||
Type getNestedTypeValue(Identifier Name) const {
|
Type getNestedTypeValue(Identifier Name) const {
|
||||||
return getNestedType(Name).getValue();
|
return getNestedType(Name).getValue();
|
||||||
}
|
}
|
||||||
@@ -3907,10 +3926,14 @@ public:
|
|||||||
void setNestedTypes(ASTContext &Ctx,
|
void setNestedTypes(ASTContext &Ctx,
|
||||||
MutableArrayRef<std::pair<Identifier, NestedType>> Nested);
|
MutableArrayRef<std::pair<Identifier, NestedType>> Nested);
|
||||||
|
|
||||||
|
/// Register a nested type with the given name.
|
||||||
|
void registerNestedType(Identifier name, NestedType nested);
|
||||||
|
|
||||||
/// isPrimary - Determine whether this is the archetype for a 'primary'
|
/// isPrimary - Determine whether this is the archetype for a 'primary'
|
||||||
/// archetype, e.g.,
|
/// archetype, e.g., one that is not nested within another archetype and is
|
||||||
|
/// not an opened existential.
|
||||||
bool isPrimary() const {
|
bool isPrimary() const {
|
||||||
return ParentOrOpened.isNull();
|
return ParentOrOpenedOrEnvironment.is<GenericEnvironment *>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getPrimary - Return the primary archetype parent of this archetype.
|
/// getPrimary - Return the primary archetype parent of this archetype.
|
||||||
@@ -3937,14 +3960,23 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ArchetypeType(
|
ArchetypeType(
|
||||||
const ASTContext &Ctx, ArchetypeType *Parent,
|
const ASTContext &Ctx,
|
||||||
|
llvm::PointerUnion<ArchetypeType *, GenericEnvironment *>
|
||||||
|
ParentOrGenericEnv,
|
||||||
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName,
|
llvm::PointerUnion<AssociatedTypeDecl *, Identifier> AssocTypeOrName,
|
||||||
ArrayRef<ProtocolDecl *> ConformsTo,
|
ArrayRef<ProtocolDecl *> ConformsTo,
|
||||||
Type Superclass)
|
Type Superclass)
|
||||||
: SubstitutableType(TypeKind::Archetype, &Ctx,
|
: SubstitutableType(TypeKind::Archetype, &Ctx,
|
||||||
RecursiveTypeProperties::HasArchetype),
|
RecursiveTypeProperties::HasArchetype),
|
||||||
ConformsTo(ConformsTo), Superclass(Superclass), ParentOrOpened(Parent),
|
ConformsTo(ConformsTo), Superclass(Superclass),
|
||||||
AssocTypeOrName(AssocTypeOrName) { }
|
AssocTypeOrName(AssocTypeOrName) {
|
||||||
|
if (auto parent = ParentOrGenericEnv.dyn_cast<ArchetypeType *>()) {
|
||||||
|
ParentOrOpenedOrEnvironment = parent;
|
||||||
|
} else {
|
||||||
|
ParentOrOpenedOrEnvironment =
|
||||||
|
ParentOrGenericEnv.get<GenericEnvironment *>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ArchetypeType(const ASTContext &Ctx,
|
ArchetypeType(const ASTContext &Ctx,
|
||||||
Type Existential,
|
Type Existential,
|
||||||
@@ -3955,7 +3987,7 @@ private:
|
|||||||
RecursiveTypeProperties::HasArchetype |
|
RecursiveTypeProperties::HasArchetype |
|
||||||
RecursiveTypeProperties::HasOpenedExistential)),
|
RecursiveTypeProperties::HasOpenedExistential)),
|
||||||
ConformsTo(ConformsTo), Superclass(Superclass),
|
ConformsTo(ConformsTo), Superclass(Superclass),
|
||||||
ParentOrOpened(Existential.getPointer()) { }
|
ParentOrOpenedOrEnvironment(Existential.getPointer()) { }
|
||||||
};
|
};
|
||||||
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
|
BEGIN_CAN_TYPE_WRAPPER(ArchetypeType, SubstitutableType)
|
||||||
CanArchetypeType getParent() const {
|
CanArchetypeType getParent() const {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "swift/AST/ProtocolConformance.h"
|
#include "swift/AST/ProtocolConformance.h"
|
||||||
#include "swift/AST/TypeRepr.h"
|
#include "swift/AST/TypeRepr.h"
|
||||||
#include "swift/AST/TypeWalker.h"
|
#include "swift/AST/TypeWalker.h"
|
||||||
|
#include "swift/Basic/Defer.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
@@ -130,6 +131,24 @@ struct ArchetypeBuilder::Implementation {
|
|||||||
|
|
||||||
/// The nested types that have been renamed.
|
/// The nested types that have been renamed.
|
||||||
SmallVector<PotentialArchetype *, 4> RenamedNestedTypes;
|
SmallVector<PotentialArchetype *, 4> RenamedNestedTypes;
|
||||||
|
|
||||||
|
/// Potential archetypes for which we are currently performing
|
||||||
|
/// substitutions of their superclasses. Used to detect recursion in
|
||||||
|
/// superclass substitutions.
|
||||||
|
llvm::DenseSet<std::pair<GenericEnvironment *,
|
||||||
|
ArchetypeBuilder::PotentialArchetype *>>
|
||||||
|
SuperclassSubs;
|
||||||
|
|
||||||
|
/// Potential archetypes for which we are currently performing
|
||||||
|
/// substitutions of their concrete types. Used to detect recursion in
|
||||||
|
/// concrete type substitutions.
|
||||||
|
llvm::DenseSet<std::pair<GenericEnvironment *,
|
||||||
|
ArchetypeBuilder::PotentialArchetype *>>
|
||||||
|
ConcreteSubs;
|
||||||
|
|
||||||
|
/// FIXME: Egregious hack to track when we ended up using a "parent"
|
||||||
|
/// archetype, because we end up with broken invariants in that case.
|
||||||
|
bool UsedContextArchetype = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ArchetypeBuilder::PotentialArchetype::~PotentialArchetype() {
|
ArchetypeBuilder::PotentialArchetype::~PotentialArchetype() {
|
||||||
@@ -363,10 +382,13 @@ auto ArchetypeBuilder::PotentialArchetype::getRepresentative()
|
|||||||
|
|
||||||
bool ArchetypeBuilder::PotentialArchetype::hasConcreteTypeInPath() const {
|
bool ArchetypeBuilder::PotentialArchetype::hasConcreteTypeInPath() const {
|
||||||
for (auto pa = this; pa; pa = pa->getParent()) {
|
for (auto pa = this; pa; pa = pa->getParent()) {
|
||||||
if (pa->ArchetypeOrConcreteType.isConcreteType() &&
|
// FIXME: The archetype check here is a hack because we're reusing
|
||||||
!pa->ArchetypeOrConcreteType.getAsConcreteType()->is<ArchetypeType>())
|
// archetypes from the outer context.
|
||||||
|
if (Type concreteType = pa->getConcreteType()) {
|
||||||
|
if (!concreteType->is<ArchetypeType>())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -479,7 +501,7 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
|
|||||||
// to resolve and get a special diagnosis in finalize.
|
// to resolve and get a special diagnosis in finalize.
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
pa->ArchetypeOrConcreteType = NestedType::forConcreteType(type);
|
pa->ConcreteType = type;
|
||||||
pa->SameTypeSource = redundantSource;
|
pa->SameTypeSource = redundantSource;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@@ -536,10 +558,16 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
|
|||||||
|
|
||||||
/// Replace dependent types with their archetypes or concrete types.
|
/// Replace dependent types with their archetypes or concrete types.
|
||||||
static Type substConcreteTypesForDependentTypes(ArchetypeBuilder &builder,
|
static Type substConcreteTypesForDependentTypes(ArchetypeBuilder &builder,
|
||||||
|
GenericEnvironment *genericEnv,
|
||||||
Type type) {
|
Type type) {
|
||||||
|
// FIXME: Use dyn_cast rather than getAs.
|
||||||
|
// FIXME: This should really be "Type::subst()", but we need a way to provide
|
||||||
|
// Type::subst() with generic parameter bindings that are lazily populated
|
||||||
|
// through the archetype builder.
|
||||||
return type.transform([&](Type type) -> Type {
|
return type.transform([&](Type type) -> Type {
|
||||||
if (auto depMemTy = type->getAs<DependentMemberType>()) {
|
if (auto depMemTy = type->getAs<DependentMemberType>()) {
|
||||||
auto newBase = substConcreteTypesForDependentTypes(builder,
|
auto newBase = substConcreteTypesForDependentTypes(builder,
|
||||||
|
genericEnv,
|
||||||
depMemTy->getBase());
|
depMemTy->getBase());
|
||||||
return depMemTy->substBaseType(&builder.getModule(), newBase,
|
return depMemTy->substBaseType(&builder.getModule(), newBase,
|
||||||
builder.getLazyResolver());
|
builder.getLazyResolver());
|
||||||
@@ -547,7 +575,8 @@ static Type substConcreteTypesForDependentTypes(ArchetypeBuilder &builder,
|
|||||||
|
|
||||||
if (auto typeParam = type->getAs<GenericTypeParamType>()) {
|
if (auto typeParam = type->getAs<GenericTypeParamType>()) {
|
||||||
auto potentialArchetype = builder.resolveArchetype(typeParam);
|
auto potentialArchetype = builder.resolveArchetype(typeParam);
|
||||||
return potentialArchetype->getType(builder).getValue();
|
return potentialArchetype->getTypeInContext(builder, genericEnv)
|
||||||
|
.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
@@ -555,83 +584,93 @@ static Type substConcreteTypesForDependentTypes(ArchetypeBuilder &builder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArchetypeType::NestedType
|
ArchetypeType::NestedType
|
||||||
ArchetypeBuilder::PotentialArchetype::getType(ArchetypeBuilder &builder) {
|
ArchetypeBuilder::PotentialArchetype::getTypeInContext(
|
||||||
|
ArchetypeBuilder &builder,
|
||||||
auto representative = getRepresentative();
|
GenericEnvironment *genericEnv) {
|
||||||
ASTContext &ctx = getRootParam()->getASTContext();
|
|
||||||
|
|
||||||
// Retrieve the archetype from the archetype anchor in this equivalence class.
|
// Retrieve the archetype from the archetype anchor in this equivalence class.
|
||||||
// The anchor must not have any concrete parents (otherwise we would just
|
// The anchor must not have any concrete parents (otherwise we would just
|
||||||
// use the representative).
|
// use the representative).
|
||||||
auto archetypeAnchor = getArchetypeAnchor();
|
auto archetypeAnchor = getArchetypeAnchor();
|
||||||
if (archetypeAnchor != this)
|
if (archetypeAnchor != this)
|
||||||
return archetypeAnchor->getType(builder);
|
return archetypeAnchor->getTypeInContext(builder, genericEnv);
|
||||||
|
|
||||||
|
auto representative = getRepresentative();
|
||||||
|
ASTContext &ctx = getRootParam()->getASTContext();
|
||||||
|
|
||||||
// Return a concrete type or archetype we've already resolved.
|
// Return a concrete type or archetype we've already resolved.
|
||||||
if (representative->ArchetypeOrConcreteType) {
|
if (Type concreteType = representative->getConcreteType()) {
|
||||||
// If the concrete type is dependent, substitute dependent types
|
// If the concrete type doesn't involve type parameters, just return it.
|
||||||
// for archetypes.
|
if (!concreteType->hasTypeParameter())
|
||||||
if (auto concreteType
|
return NestedType::forConcreteType(concreteType);
|
||||||
= representative->ArchetypeOrConcreteType.getAsConcreteType()) {
|
|
||||||
if (concreteType->hasTypeParameter()) {
|
|
||||||
// If we already know the concrete type is recursive, just
|
|
||||||
// return an error. It will be diagnosed elsewhere.
|
|
||||||
if (representative->RecursiveConcreteType) {
|
|
||||||
return NestedType::forConcreteType(ErrorType::get(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're already substituting a concrete type, mark this
|
// Otherwise, substitute in the archetypes in the environment.
|
||||||
|
|
||||||
|
// If we're already substituting into the concrete type, mark this
|
||||||
// potential archetype as having a recursive concrete type.
|
// potential archetype as having a recursive concrete type.
|
||||||
if (representative->SubstitutingConcreteType) {
|
if (representative->RecursiveConcreteType ||
|
||||||
representative->RecursiveConcreteType = true;
|
!builder.Impl->ConcreteSubs.insert({genericEnv, representative})
|
||||||
return NestedType::forConcreteType(ErrorType::get(ctx));
|
.second) {
|
||||||
}
|
// Complain about the recursion, if we haven't done so already.
|
||||||
|
if (!representative->RecursiveConcreteType) {
|
||||||
representative->SubstitutingConcreteType = true;
|
ctx.Diags.diagnose(representative->SameTypeSource->getLoc(),
|
||||||
NestedType result = NestedType::forConcreteType(
|
|
||||||
substConcreteTypesForDependentTypes(
|
|
||||||
builder,
|
|
||||||
concreteType));
|
|
||||||
representative->SubstitutingConcreteType = false;
|
|
||||||
|
|
||||||
// If all went well, we're done.
|
|
||||||
if (!representative->RecursiveConcreteType)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Otherwise, we found that the concrete type is recursive,
|
|
||||||
// complain and return an error.
|
|
||||||
ctx.Diags.diagnose(SameTypeSource->getLoc(),
|
|
||||||
diag::recursive_same_type_constraint,
|
diag::recursive_same_type_constraint,
|
||||||
getDependentType(/*allowUnresolved=*/false),
|
getDependentType(/*allowUnresolved=*/true),
|
||||||
concreteType);
|
concreteType);
|
||||||
|
|
||||||
return NestedType::forConcreteType(ErrorType::get(ctx));
|
representative->RecursiveConcreteType = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return representative->ArchetypeOrConcreteType;
|
return NestedType::forConcreteType(
|
||||||
|
ErrorType::get(getDependentType(/*allowUnresolved=*/true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SWIFT_DEFER {
|
||||||
|
builder.Impl->ConcreteSubs.erase({genericEnv, representative});
|
||||||
|
};
|
||||||
|
|
||||||
|
return NestedType::forConcreteType(
|
||||||
|
substConcreteTypesForDependentTypes(builder, genericEnv,
|
||||||
|
concreteType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we haven't referenced this type while substituting into the
|
||||||
|
// superclass.
|
||||||
|
if (!representative->RecursiveSuperclassType &&
|
||||||
|
representative->getSuperclass() &&
|
||||||
|
builder.Impl->SuperclassSubs.count({genericEnv, representative})
|
||||||
|
> 0) {
|
||||||
|
if (representative->SuperclassSource->getLoc().isValid()) {
|
||||||
|
ctx.Diags.diagnose(representative->SuperclassSource->getLoc(),
|
||||||
|
diag::recursive_superclass_constraint,
|
||||||
|
representative->getSuperclass());
|
||||||
|
}
|
||||||
|
|
||||||
|
representative->RecursiveSuperclassType = true;
|
||||||
|
return NestedType::forConcreteType(
|
||||||
|
ErrorType::get(getDependentType(/*allowUnresolved=*/true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
AssociatedTypeDecl *assocType = nullptr;
|
AssociatedTypeDecl *assocType = nullptr;
|
||||||
|
|
||||||
// Allocate a new archetype.
|
|
||||||
ArchetypeType *ParentArchetype = nullptr;
|
ArchetypeType *ParentArchetype = nullptr;
|
||||||
auto &mod = builder.getModule();
|
|
||||||
if (auto parent = getParent()) {
|
if (auto parent = getParent()) {
|
||||||
auto parentTy = parent->getType(builder);
|
// For nested types, first substitute into the parent so we can form the
|
||||||
|
// proper nested type.
|
||||||
|
auto &mod = builder.getModule();
|
||||||
|
|
||||||
|
auto parentTy = parent->getTypeInContext(builder, genericEnv);
|
||||||
if (!parentTy)
|
if (!parentTy)
|
||||||
return NestedType::forConcreteType(ErrorType::get(ctx));
|
return NestedType::forConcreteType(ErrorType::get(ctx));
|
||||||
|
|
||||||
ParentArchetype = parentTy.getAsArchetype();
|
if (Type concreteParent = parentTy.getAsConcreteType()) {
|
||||||
if (!ParentArchetype) {
|
|
||||||
// We might have an outer archetype as a concrete type here; if so, just
|
// We might have an outer archetype as a concrete type here; if so, just
|
||||||
// return that.
|
// return that.
|
||||||
ParentArchetype = parentTy.getValue()->getAs<ArchetypeType>();
|
// FIXME: This should go away when we fix
|
||||||
if (ParentArchetype) {
|
// ArchetypeBuilder::addGenericSignature() to no longer take a generic
|
||||||
representative->ArchetypeOrConcreteType
|
// environment.
|
||||||
= NestedType::forConcreteType(
|
if (auto parentArchetype = concreteParent->getAs<ArchetypeType>()) {
|
||||||
ParentArchetype->getNestedTypeValue(getName()));
|
builder.Impl->UsedContextArchetype = true;
|
||||||
return representative->ArchetypeOrConcreteType;
|
return NestedType::forConcreteType(
|
||||||
|
parentArchetype->getNestedTypeValue(getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyResolver *resolver = ctx.getLazyResolver();
|
LazyResolver *resolver = ctx.getLazyResolver();
|
||||||
@@ -644,39 +683,51 @@ ArchetypeBuilder::PotentialArchetype::getType(ArchetypeBuilder &builder) {
|
|||||||
return NestedType::forConcreteType(type);
|
return NestedType::forConcreteType(type);
|
||||||
|
|
||||||
auto depMemberType = type->castTo<DependentMemberType>();
|
auto depMemberType = type->castTo<DependentMemberType>();
|
||||||
Type memberType = depMemberType->substBaseType(
|
Type memberType = depMemberType->substBaseType(&mod, parentTy.getValue(),
|
||||||
&mod,
|
|
||||||
parent->ArchetypeOrConcreteType.getAsConcreteType(),
|
|
||||||
resolver);
|
resolver);
|
||||||
if (auto memberPA = builder.resolveArchetype(memberType)) {
|
|
||||||
// If the member type maps to an archetype, resolve that archetype.
|
// If the member type maps to an archetype, resolve that archetype.
|
||||||
if (memberPA->getRepresentative() != getRepresentative()) {
|
if (auto memberPA = builder.resolveArchetype(memberType)) {
|
||||||
representative->ArchetypeOrConcreteType = memberPA->getType(builder);
|
if (memberPA->getRepresentative() != representative) {
|
||||||
return representative->ArchetypeOrConcreteType;
|
return memberPA->getTypeInContext(builder, genericEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("we have no parent archetype");
|
llvm_unreachable("we have no parent archetype");
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
|
||||||
// Otherwise, it's a concrete type.
|
// Otherwise, it's a concrete type.
|
||||||
representative->ArchetypeOrConcreteType
|
|
||||||
= NestedType::forConcreteType(
|
// FIXME: THIS ASSIGNMENT IS REALLY WEIRD. We shouldn't be discovering
|
||||||
substConcreteTypesForDependentTypes(builder, memberType));
|
// that a same-type constraint affects this so late in the game.
|
||||||
representative->SameTypeSource = parent->SameTypeSource;
|
representative->SameTypeSource = parent->SameTypeSource;
|
||||||
|
|
||||||
return representative->ArchetypeOrConcreteType;
|
return NestedType::forConcreteType(
|
||||||
}
|
substConcreteTypesForDependentTypes(builder, genericEnv,
|
||||||
|
memberType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParentArchetype = parentTy.getAsArchetype();
|
||||||
|
|
||||||
|
// Check whether the parent already has an nested type with this name. If
|
||||||
|
// so, return it directly.
|
||||||
|
if (auto nested = ParentArchetype->getNestedTypeIfKnown(getName()))
|
||||||
|
return *nested;
|
||||||
|
|
||||||
|
// We will build the archetype below.
|
||||||
assocType = getResolvedAssociatedType();
|
assocType = getResolvedAssociatedType();
|
||||||
|
} else if (auto type = genericEnv->getMappingIfPresent(getGenericParam())) {
|
||||||
|
// We already have a mapping for this generic parameter in the generic
|
||||||
|
// environment. Return it.
|
||||||
|
if (auto archetype = (*type)->getAs<ArchetypeType>())
|
||||||
|
return NestedType::forArchetype(archetype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we ended up building our parent archetype, then we'll have
|
// Build a new archetype.
|
||||||
// already filled in our own archetype.
|
|
||||||
if (auto arch = representative->ArchetypeOrConcreteType.getAsArchetype())
|
|
||||||
return NestedType::forArchetype(arch);
|
|
||||||
|
|
||||||
|
// Collect the protocol conformances for the archetype.
|
||||||
SmallVector<ProtocolDecl *, 4> Protos;
|
SmallVector<ProtocolDecl *, 4> Protos;
|
||||||
for (const auto &conforms : ConformsTo) {
|
for (const auto &conforms : representative->getConformsTo()) {
|
||||||
switch (conforms.second.getKind()) {
|
switch (conforms.second.getKind()) {
|
||||||
case RequirementSource::Explicit:
|
case RequirementSource::Explicit:
|
||||||
case RequirementSource::Inferred:
|
case RequirementSource::Inferred:
|
||||||
@@ -692,48 +743,56 @@ ArchetypeBuilder::PotentialArchetype::getType(ArchetypeBuilder &builder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type superclass;
|
// Create the archetype.
|
||||||
|
//
|
||||||
if (Superclass) {
|
// Note that we delay the computation of the superclass until after we
|
||||||
if (representative->RecursiveSuperclassType) {
|
// create the archetype, in case the superclass references the archetype
|
||||||
ctx.Diags.diagnose(SuperclassSource->getLoc(),
|
// itself.
|
||||||
diag::recursive_superclass_constraint,
|
|
||||||
Superclass);
|
|
||||||
} else {
|
|
||||||
representative->RecursiveSuperclassType = true;
|
|
||||||
assert(!Superclass->hasArchetype() &&
|
|
||||||
"superclass constraint must use interface types");
|
|
||||||
superclass = substConcreteTypesForDependentTypes(builder, Superclass);
|
|
||||||
representative->RecursiveSuperclassType = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchetypeType *arch;
|
ArchetypeType *arch;
|
||||||
if (ParentArchetype) {
|
if (ParentArchetype) {
|
||||||
// If we were unable to resolve this as an associated type, produce an
|
// If we were unable to resolve this as an associated type, produce an
|
||||||
// error type.
|
// error type.
|
||||||
if (!assocType) {
|
if (!assocType) {
|
||||||
representative->ArchetypeOrConcreteType =
|
return NestedType::forConcreteType(
|
||||||
NestedType::forConcreteType(
|
|
||||||
ErrorType::get(getDependentType(/*allowUnresolved=*/true)));
|
ErrorType::get(getDependentType(/*allowUnresolved=*/true)));
|
||||||
|
|
||||||
return representative->ArchetypeOrConcreteType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a nested archetype.
|
||||||
arch = ArchetypeType::getNew(ctx, ParentArchetype, assocType, Protos,
|
arch = ArchetypeType::getNew(ctx, ParentArchetype, assocType, Protos,
|
||||||
superclass);
|
Type());
|
||||||
|
|
||||||
|
// Register this archetype with its parent.
|
||||||
|
ParentArchetype->registerNestedType(getName(),
|
||||||
|
NestedType::forArchetype(arch));
|
||||||
} else {
|
} else {
|
||||||
arch = ArchetypeType::getNew(ctx, getName(), Protos, superclass);
|
// Create a top-level archetype.
|
||||||
|
arch = ArchetypeType::getNew(ctx, genericEnv, getName(), Protos, Type());
|
||||||
|
|
||||||
|
// Register the archetype with the generic environment.
|
||||||
|
genericEnv->addMapping(getGenericParam(), arch);
|
||||||
}
|
}
|
||||||
|
|
||||||
representative->ArchetypeOrConcreteType = NestedType::forArchetype(arch);
|
// Determine the superclass for the archetype. If it exists and involves
|
||||||
|
// type parameters, substitute them.
|
||||||
|
if (Type superclass = representative->getSuperclass()) {
|
||||||
|
if (superclass->hasTypeParameter()) {
|
||||||
|
(void)builder.Impl->SuperclassSubs.insert({genericEnv, representative});
|
||||||
|
SWIFT_DEFER {
|
||||||
|
builder.Impl->SuperclassSubs.erase({genericEnv, representative});
|
||||||
|
};
|
||||||
|
superclass = substConcreteTypesForDependentTypes(builder, genericEnv,
|
||||||
|
superclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
arch->setSuperclass(superclass);
|
||||||
|
}
|
||||||
|
|
||||||
// Collect the set of nested types of this archetype, and put them into
|
// Collect the set of nested types of this archetype, and put them into
|
||||||
// the archetype itself.
|
// the archetype itself.
|
||||||
if (!NestedTypes.empty()) {
|
if (!representative->getNestedTypes().empty()) {
|
||||||
ctx.registerLazyArchetype(arch, builder, this);
|
ctx.registerLazyArchetype(arch, builder, this);
|
||||||
SmallVector<std::pair<Identifier, NestedType>, 4> FlatNestedTypes;
|
SmallVector<std::pair<Identifier, NestedType>, 4> FlatNestedTypes;
|
||||||
for (auto Nested : NestedTypes) {
|
for (auto Nested : representative->getNestedTypes()) {
|
||||||
// Skip type aliases, which are just shortcuts.
|
// Skip type aliases, which are just shortcuts.
|
||||||
if (Nested.second.front()->getTypeAliasDecl())
|
if (Nested.second.front()->getTypeAliasDecl())
|
||||||
continue;
|
continue;
|
||||||
@@ -761,6 +820,24 @@ ArchetypeBuilder::PotentialArchetype::getType(ArchetypeBuilder &builder) {
|
|||||||
return NestedType::forArchetype(arch);
|
return NestedType::forArchetype(arch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchetypeType::resolveNestedType(
|
||||||
|
std::pair<Identifier, NestedType> &nested) const {
|
||||||
|
auto &ctx = const_cast<ArchetypeType *>(this)->getASTContext();
|
||||||
|
auto lazyArchetype = ctx.getLazyArchetype(this);
|
||||||
|
|
||||||
|
ArchetypeBuilder &builder = *lazyArchetype.first;
|
||||||
|
auto genericEnv = getGenericEnvironment();
|
||||||
|
auto potentialArchetype =
|
||||||
|
lazyArchetype.second->getNestedType(nested.first, builder);
|
||||||
|
|
||||||
|
auto result = potentialArchetype->getTypeInContext(builder, genericEnv);
|
||||||
|
assert(!nested.second ||
|
||||||
|
nested.second.getValue()->isEqual(result.getValue()) ||
|
||||||
|
(nested.second.getValue()->hasError() &&
|
||||||
|
result.getValue()->hasError()));
|
||||||
|
nested.second = result;
|
||||||
|
}
|
||||||
|
|
||||||
Type ArchetypeBuilder::PotentialArchetype::getDependentType(
|
Type ArchetypeBuilder::PotentialArchetype::getDependentType(
|
||||||
bool allowUnresolved) {
|
bool allowUnresolved) {
|
||||||
if (auto parent = getParent()) {
|
if (auto parent = getParent()) {
|
||||||
@@ -1216,8 +1293,8 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
|
|||||||
std::swap(T1, T2);
|
std::swap(T1, T2);
|
||||||
|
|
||||||
// Merge any concrete constraints.
|
// Merge any concrete constraints.
|
||||||
Type concrete1 = T1->ArchetypeOrConcreteType.getAsConcreteType();
|
Type concrete1 = T1->getConcreteType();
|
||||||
Type concrete2 = T2->ArchetypeOrConcreteType.getAsConcreteType();
|
Type concrete2 = T2->getConcreteType();
|
||||||
|
|
||||||
if (concrete1 && concrete2) {
|
if (concrete1 && concrete2) {
|
||||||
if (!concrete1->isEqual(concrete2)) {
|
if (!concrete1->isEqual(concrete2)) {
|
||||||
@@ -1227,14 +1304,14 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else if (concrete1) {
|
} else if (concrete1) {
|
||||||
assert(!T2->ArchetypeOrConcreteType
|
assert(!T2->ConcreteType
|
||||||
&& "already formed archetype for concrete-constrained parameter");
|
&& "already formed archetype for concrete-constrained parameter");
|
||||||
T2->ArchetypeOrConcreteType = NestedType::forConcreteType(concrete1);
|
T2->ConcreteType = concrete1;
|
||||||
T2->SameTypeSource = T1->SameTypeSource;
|
T2->SameTypeSource = T1->SameTypeSource;
|
||||||
} else if (concrete2) {
|
} else if (concrete2) {
|
||||||
assert(!T1->ArchetypeOrConcreteType
|
assert(!T1->ConcreteType
|
||||||
&& "already formed archetype for concrete-constrained parameter");
|
&& "already formed archetype for concrete-constrained parameter");
|
||||||
T1->ArchetypeOrConcreteType = NestedType::forConcreteType(concrete2);
|
T1->ConcreteType = concrete2;
|
||||||
T1->SameTypeSource = T2->SameTypeSource;
|
T1->SameTypeSource = T2->SameTypeSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1289,12 +1366,9 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
|
|||||||
// Operate on the representative.
|
// Operate on the representative.
|
||||||
T = T->getRepresentative();
|
T = T->getRepresentative();
|
||||||
|
|
||||||
assert(!T->ArchetypeOrConcreteType.getAsArchetype()
|
|
||||||
&& "already formed archetype for concrete-constrained parameter");
|
|
||||||
|
|
||||||
// If we've already been bound to a type, we're either done, or we have a
|
// If we've already been bound to a type, we're either done, or we have a
|
||||||
// problem.
|
// problem.
|
||||||
if (auto oldConcrete = T->ArchetypeOrConcreteType.getAsConcreteType()) {
|
if (auto oldConcrete = T->getConcreteType()) {
|
||||||
if (!oldConcrete->isEqual(Concrete)) {
|
if (!oldConcrete->isEqual(Concrete)) {
|
||||||
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
|
Diags.diagnose(Source.getLoc(), diag::requires_same_type_conflict,
|
||||||
T->getName(), oldConcrete, Concrete);
|
T->getName(), oldConcrete, Concrete);
|
||||||
@@ -1322,7 +1396,7 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Record the requirement.
|
// Record the requirement.
|
||||||
T->ArchetypeOrConcreteType = NestedType::forConcreteType(Concrete);
|
T->ConcreteType = Concrete;
|
||||||
T->SameTypeSource = Source;
|
T->SameTypeSource = Source;
|
||||||
|
|
||||||
// Make sure the concrete type fulfills the superclass requirement
|
// Make sure the concrete type fulfills the superclass requirement
|
||||||
@@ -1819,7 +1893,7 @@ ArchetypeBuilder::finalize(SourceLoc loc, bool allowConcreteGenericParams) {
|
|||||||
|
|
||||||
// Don't allow a generic parameter to be equivalent to a concrete type,
|
// Don't allow a generic parameter to be equivalent to a concrete type,
|
||||||
// because then we don't actually have a parameter.
|
// because then we don't actually have a parameter.
|
||||||
if (rep->ArchetypeOrConcreteType.getAsConcreteType()) {
|
if (rep->getConcreteType()) {
|
||||||
auto &Source = rep->SameTypeSource;
|
auto &Source = rep->SameTypeSource;
|
||||||
|
|
||||||
// For auto-generated locations, we should have diagnosed the problem
|
// For auto-generated locations, we should have diagnosed the problem
|
||||||
@@ -2111,7 +2185,7 @@ void ArchetypeBuilder::addGenericSignature(GenericSignature *sig,
|
|||||||
assert(Impl->PotentialArchetypes.count(key) && "Missing parameter?");
|
assert(Impl->PotentialArchetypes.count(key) && "Missing parameter?");
|
||||||
auto *pa = Impl->PotentialArchetypes[key];
|
auto *pa = Impl->PotentialArchetypes[key];
|
||||||
assert(pa == pa->getRepresentative() && "Not the representative");
|
assert(pa == pa->getRepresentative() && "Not the representative");
|
||||||
pa->ArchetypeOrConcreteType = NestedType::forConcreteType(contextTy);
|
pa->ConcreteType = contextTy;
|
||||||
pa->SameTypeSource = RequirementSource(sourceKind, SourceLoc());
|
pa->SameTypeSource = RequirementSource(sourceKind, SourceLoc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2185,38 +2259,33 @@ GenericSignature *ArchetypeBuilder::getGenericSignature() {
|
|||||||
GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(GenericSignature *signature) {
|
GenericEnvironment *ArchetypeBuilder::getGenericEnvironment(GenericSignature *signature) {
|
||||||
TypeSubstitutionMap interfaceToArchetypeMap;
|
TypeSubstitutionMap interfaceToArchetypeMap;
|
||||||
|
|
||||||
|
// Compute the archetypes for the generic parameters.
|
||||||
auto genericEnv = GenericEnvironment::getIncomplete(Context, signature);
|
auto genericEnv = GenericEnvironment::getIncomplete(Context, signature);
|
||||||
SmallVector<std::pair<const GenericTypeParamKey, PotentialArchetype *>, 2>
|
|
||||||
delayedPAs;
|
|
||||||
for (auto pair : Impl->PotentialArchetypes) {
|
for (auto pair : Impl->PotentialArchetypes) {
|
||||||
// If this potential archetype won't map directly to a primary archetype,
|
Type contextType =
|
||||||
// skip it for now.
|
pair.second->getTypeInContext(*this, genericEnv).getValue();
|
||||||
if (pair.second->isConcreteType() ||
|
if (!genericEnv->getMappingIfPresent(pair.second->getGenericParam()))
|
||||||
pair.second->getRepresentative() != pair.second) {
|
genericEnv->addMapping(pair.second->getGenericParam(), contextType);
|
||||||
delayedPAs.push_back(pair);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the mapping for this primary archetype.
|
#ifndef NDEBUG
|
||||||
auto paramTy = pair.second->getGenericParam();
|
// FIXME: This property should be maintained when there are errors, too.
|
||||||
auto archetype = pair.second->getType(*this).getAsArchetype();
|
if (!Diags.hadAnyError() && !Impl->UsedContextArchetype) {
|
||||||
genericEnv->addMapping(paramTy, archetype);
|
visitPotentialArchetypes([&](PotentialArchetype *pa) {
|
||||||
}
|
if (pa->isConcreteType()) return;
|
||||||
|
|
||||||
// Add the mapping for any potential archetypes we delayed because they
|
auto depTy = pa->getDependentType(/*allowUnresolved=*/false);
|
||||||
// depend on other archetypes.
|
auto inContext = genericEnv->mapTypeIntoContext(&getModule(), depTy);
|
||||||
for (auto pair : delayedPAs) {
|
|
||||||
auto paramTy = pair.second->getGenericParam();
|
|
||||||
|
|
||||||
auto archetypeTy = pair.second->getType(*this).getAsArchetype();
|
auto repDepTy = pa->getRepresentative()->getDependentType(
|
||||||
auto concreteTy = pair.second->getType(*this).getAsConcreteType();
|
/*allowUnresolved=*/false);
|
||||||
if (archetypeTy)
|
auto repInContext = genericEnv->mapTypeIntoContext(&getModule(), repDepTy);
|
||||||
genericEnv->addMapping(paramTy, archetypeTy);
|
assert((inContext->isEqual(repInContext) ||
|
||||||
else if (concreteTy)
|
(inContext->hasError() && repInContext->hasError())) &&
|
||||||
genericEnv->addMapping(paramTy, concreteTy);
|
"Potential archetype mapping differs from representative!");
|
||||||
else
|
});
|
||||||
llvm_unreachable("broken generic parameter");
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return genericEnv;
|
return genericEnv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -427,7 +427,8 @@ createGenericParam(ASTContext &ctx, const char *name, unsigned index) {
|
|||||||
Module *M = ctx.TheBuiltinModule;
|
Module *M = ctx.TheBuiltinModule;
|
||||||
Identifier ident = ctx.getIdentifier(name);
|
Identifier ident = ctx.getIdentifier(name);
|
||||||
SmallVector<ProtocolDecl *, 1> protos;
|
SmallVector<ProtocolDecl *, 1> protos;
|
||||||
ArchetypeType *archetype = ArchetypeType::getNew(ctx, ident, protos, Type());
|
ArchetypeType *archetype = ArchetypeType::getNew(ctx, nullptr, ident, protos,
|
||||||
|
Type());
|
||||||
auto genericParam =
|
auto genericParam =
|
||||||
new (ctx) GenericTypeParamDecl(&M->getMainFile(FileUnitKind::Builtin),
|
new (ctx) GenericTypeParamDecl(&M->getMainFile(FileUnitKind::Builtin),
|
||||||
ident, SourceLoc(), 0, index);
|
ident, SourceLoc(), 0, index);
|
||||||
|
|||||||
@@ -68,6 +68,17 @@ void GenericEnvironment::addMapping(GenericTypeParamType *genericParam,
|
|||||||
result.first->second = genericParam;
|
result.first->second = genericParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<Type> GenericEnvironment::getMappingIfPresent(
|
||||||
|
GenericTypeParamType *genericParam) const {
|
||||||
|
auto canParamTy =
|
||||||
|
cast<GenericTypeParamType>(genericParam->getCanonicalType());
|
||||||
|
|
||||||
|
auto found = InterfaceToArchetypeMap.find(canParamTy);
|
||||||
|
if (found == InterfaceToArchetypeMap.end()) return None;
|
||||||
|
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
|
||||||
void *GenericEnvironment::operator new(size_t bytes, const ASTContext &ctx) {
|
void *GenericEnvironment::operator new(size_t bytes, const ASTContext &ctx) {
|
||||||
return ctx.Allocate(bytes, alignof(GenericEnvironment), AllocationArena::Permanent);
|
return ctx.Allocate(bytes, alignof(GenericEnvironment), AllocationArena::Permanent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2483,7 +2483,9 @@ CanArchetypeType ArchetypeType::getNew(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CanArchetypeType
|
CanArchetypeType
|
||||||
ArchetypeType::getNew(const ASTContext &Ctx, Identifier Name,
|
ArchetypeType::getNew(const ASTContext &Ctx,
|
||||||
|
GenericEnvironment *genericEnvironment,
|
||||||
|
Identifier Name,
|
||||||
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
SmallVectorImpl<ProtocolDecl *> &ConformsTo,
|
||||||
Type Superclass) {
|
Type Superclass) {
|
||||||
// Gather the set of protocol declarations to which this archetype conforms.
|
// Gather the set of protocol declarations to which this archetype conforms.
|
||||||
@@ -2491,7 +2493,7 @@ ArchetypeType::getNew(const ASTContext &Ctx, Identifier Name,
|
|||||||
|
|
||||||
auto arena = AllocationArena::Permanent;
|
auto arena = AllocationArena::Permanent;
|
||||||
return CanArchetypeType(
|
return CanArchetypeType(
|
||||||
new (Ctx, arena) ArchetypeType(Ctx, nullptr, Name,
|
new (Ctx, arena) ArchetypeType(Ctx, genericEnvironment, Name,
|
||||||
Ctx.AllocateCopy(ConformsTo),
|
Ctx.AllocateCopy(ConformsTo),
|
||||||
Superclass));
|
Superclass));
|
||||||
}
|
}
|
||||||
@@ -2505,15 +2507,6 @@ bool ArchetypeType::requiresClass() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchetypeType::resolveNestedType(
|
|
||||||
std::pair<Identifier, NestedType> &nested) const {
|
|
||||||
auto &ctx = const_cast<ArchetypeType *>(this)->getASTContext();
|
|
||||||
auto lazyArchetype = ctx.getLazyArchetype(this);
|
|
||||||
nested.second = lazyArchetype.second->getNestedType(nested.first,
|
|
||||||
*lazyArchetype.first)
|
|
||||||
->getType(*lazyArchetype.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// \brief Function object that orders archetypes by name.
|
/// \brief Function object that orders archetypes by name.
|
||||||
struct OrderArchetypeByName {
|
struct OrderArchetypeByName {
|
||||||
@@ -2556,6 +2549,16 @@ ArchetypeType::NestedType ArchetypeType::getNestedType(Identifier Name) const {
|
|||||||
return Pos->second;
|
return Pos->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<ArchetypeType::NestedType> ArchetypeType::getNestedTypeIfKnown(
|
||||||
|
Identifier Name) const {
|
||||||
|
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
|
||||||
|
OrderArchetypeByName());
|
||||||
|
if (Pos == NestedTypes.end() || Pos->first != Name || !Pos->second)
|
||||||
|
return None;
|
||||||
|
|
||||||
|
return Pos->second;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArchetypeType::hasNestedType(Identifier Name) const {
|
bool ArchetypeType::hasNestedType(Identifier Name) const {
|
||||||
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
|
auto Pos = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), Name,
|
||||||
OrderArchetypeByName());
|
OrderArchetypeByName());
|
||||||
@@ -2581,6 +2584,18 @@ void ArchetypeType::setNestedTypes(
|
|||||||
NestedTypes = Ctx.AllocateCopy(Nested);
|
NestedTypes = Ctx.AllocateCopy(Nested);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchetypeType::registerNestedType(Identifier name, NestedType nested) {
|
||||||
|
auto found = std::lower_bound(NestedTypes.begin(), NestedTypes.end(), name,
|
||||||
|
OrderArchetypeByName());
|
||||||
|
assert(found != NestedTypes.end() && found->first == name &&
|
||||||
|
"Unable to find nested type?");
|
||||||
|
assert(!found->second ||
|
||||||
|
found->second.getValue()->isEqual(nested.getValue()) ||
|
||||||
|
(found->second.getValue()->hasError() &&
|
||||||
|
nested.getValue()->hasError()));
|
||||||
|
found->second = nested;
|
||||||
|
}
|
||||||
|
|
||||||
static void collectFullName(const ArchetypeType *Archetype,
|
static void collectFullName(const ArchetypeType *Archetype,
|
||||||
SmallVectorImpl<char> &Result) {
|
SmallVectorImpl<char> &Result) {
|
||||||
if (auto Parent = Archetype->getParent()) {
|
if (auto Parent = Archetype->getParent()) {
|
||||||
@@ -2604,6 +2619,13 @@ std::string ArchetypeType::getFullName() const {
|
|||||||
return Result.str().str();
|
return Result.str().str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenericEnvironment *ArchetypeType::getGenericEnvironment() const {
|
||||||
|
if (auto parent = getParent())
|
||||||
|
return parent->getGenericEnvironment();
|
||||||
|
|
||||||
|
return ParentOrOpenedOrEnvironment.dyn_cast<GenericEnvironment *>();
|
||||||
|
}
|
||||||
|
|
||||||
void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID,
|
void ProtocolCompositionType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
ArrayRef<Type> Protocols) {
|
ArrayRef<Type> Protocols) {
|
||||||
for (auto P : Protocols)
|
for (auto P : Protocols)
|
||||||
|
|||||||
@@ -740,7 +740,8 @@ static void VisitNodeArchetype(
|
|||||||
|
|
||||||
if (ast) {
|
if (ast) {
|
||||||
result._types.push_back(ArchetypeType::getNew(
|
result._types.push_back(ArchetypeType::getNew(
|
||||||
*ast, ast->getIdentifier(archetype_name), conforms_to, Type()));
|
*ast, nullptr, ast->getIdentifier(archetype_name), conforms_to,
|
||||||
|
Type()));
|
||||||
} else {
|
} else {
|
||||||
result._error = "invalid ASTContext";
|
result._error = "invalid ASTContext";
|
||||||
}
|
}
|
||||||
@@ -769,7 +770,8 @@ static void VisitNodeArchetypeRef(
|
|||||||
if (ast) {
|
if (ast) {
|
||||||
SmallVector<ProtocolDecl *, 1> protocols;
|
SmallVector<ProtocolDecl *, 1> protocols;
|
||||||
result._types.push_back(ArchetypeType::getNew(
|
result._types.push_back(ArchetypeType::getNew(
|
||||||
*ast, ast->getIdentifier(archetype_name), protocols, Type()));
|
*ast, nullptr, ast->getIdentifier(archetype_name), protocols,
|
||||||
|
Type()));
|
||||||
} else {
|
} else {
|
||||||
result._error = "invalid ASTContext";
|
result._error = "invalid ASTContext";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3623,7 +3623,8 @@ Type ModuleFile::getType(TypeID TID) {
|
|||||||
archetype = ArchetypeType::getNew(ctx, parent, assocTypeDecl,
|
archetype = ArchetypeType::getNew(ctx, parent, assocTypeDecl,
|
||||||
conformances, superclass);
|
conformances, superclass);
|
||||||
} else {
|
} else {
|
||||||
archetype = ArchetypeType::getNew(ctx, getIdentifier(assocTypeOrNameID),
|
archetype = ArchetypeType::getNew(ctx, nullptr,
|
||||||
|
getIdentifier(assocTypeOrNameID),
|
||||||
conformances, superclass);
|
conformances, superclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user