Skip to content
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
3 changes: 3 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2372,6 +2372,9 @@ class TypeDecl : public ValueDecl {
return D->getKind() >= DeclKind::First_TypeDecl &&
D->getKind() <= DeclKind::Last_TypeDecl;
}

/// Compute an ordering between two type declarations that is ABI-stable.
static int compare(const TypeDecl *type1, const TypeDecl *type2);
};

/// A type declaration that can have generic parameters attached to it. Because
Expand Down
13 changes: 13 additions & 0 deletions include/swift/AST/DeclContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,19 @@ class alignas(1 << DeclContextAlignInBits) DeclContext {
= nullptr,
bool sorted = false) const;

/// Retrieve the syntactic depth of this declaration context, i.e.,
/// the number of non-module-scoped contexts.
///
/// For an extension of a nested type, the extension is depth 1.
unsigned getSyntacticDepth() const;

/// Retrieve the semantic depth of this declaration context, i.e.,
/// the number of non-module-scoped contexts.
///
/// For an extension of a nested type, the depth of the nested type itself
/// is also included.
unsigned getSemanticDepth() const;

/// \returns true if traversal was aborted, false otherwise.
bool walkContext(ASTWalker &Walker);

Expand Down
41 changes: 24 additions & 17 deletions include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1248,18 +1248,18 @@ class GenericSignatureBuilder::PotentialArchetype {
Identifier name;

/// The associated type or typealias for a resolved nested type.
TypeDecl *assocTypeOrAlias;
TypeDecl *assocTypeOrConcrete;

/// The generic parameter key for a root.
GenericParamKey genericParam;

PAIdentifier(Identifier name) : name(name) { }

PAIdentifier(AssociatedTypeDecl *assocType)
: assocTypeOrAlias(assocType) { }
: assocTypeOrConcrete(assocType) { }

PAIdentifier(TypeAliasDecl *typeAlias)
: assocTypeOrAlias(typeAlias) { }
PAIdentifier(TypeDecl *concreteDecl)
: assocTypeOrConcrete(concreteDecl) { }

PAIdentifier(GenericParamKey genericParam) : genericParam(genericParam) { }
} identifier;
Expand Down Expand Up @@ -1342,9 +1342,9 @@ class GenericSignatureBuilder::PotentialArchetype {
assert(parent != nullptr && "Not an associated type?");
}

/// \brief Construct a new potential archetype for a type alias.
PotentialArchetype(PotentialArchetype *parent, TypeAliasDecl *typeAlias)
: parentOrBuilder(parent), identifier(typeAlias),
/// \brief Construct a new potential archetype for a concrete declaration.
PotentialArchetype(PotentialArchetype *parent, TypeDecl *concreteDecl)
: parentOrBuilder(parent), identifier(concreteDecl),
isUnresolvedNestedType(false),
IsRecursive(false), Invalid(false),
DiagnosedRename(false)
Expand Down Expand Up @@ -1396,16 +1396,19 @@ class GenericSignatureBuilder::PotentialArchetype {
if (isUnresolvedNestedType)
return nullptr;

return dyn_cast<AssociatedTypeDecl>(identifier.assocTypeOrAlias);
return dyn_cast<AssociatedTypeDecl>(identifier.assocTypeOrConcrete);
}

/// Determine whether this PA is still unresolved.
bool isUnresolved() const { return isUnresolvedNestedType; }

/// Resolve the potential archetype to the given associated type.
void resolveAssociatedType(AssociatedTypeDecl *assocType,
GenericSignatureBuilder &builder);

/// Resolve the potential archetype to the given typealias.
void resolveTypeAlias(TypeAliasDecl *typealias,
GenericSignatureBuilder &builder);
void resolveConcreteType(TypeDecl *concreteDecl,
GenericSignatureBuilder &builder);

/// Determine whether this is a generic parameter.
bool isGenericParam() const {
Expand Down Expand Up @@ -1436,16 +1439,19 @@ class GenericSignatureBuilder::PotentialArchetype {
if (isUnresolvedNestedType)
return identifier.name;

return identifier.assocTypeOrAlias->getName();
return identifier.assocTypeOrConcrete->getName();
}

/// Retrieve the type alias.
TypeAliasDecl *getTypeAliasDecl() const {
/// Retrieve the concrete type declaration.
TypeDecl *getConcreteTypeDecl() const {
assert(getParent() && "not a nested type");
if (isUnresolvedNestedType)
return nullptr;

return dyn_cast<TypeAliasDecl>(identifier.assocTypeOrAlias);
if (isa<AssociatedTypeDecl>(identifier.assocTypeOrConcrete))
return nullptr;

return identifier.assocTypeOrConcrete;
}

/// Retrieve the set of protocols to which this potential archetype
Expand Down Expand Up @@ -1548,8 +1554,9 @@ class GenericSignatureBuilder::PotentialArchetype {
PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
GenericSignatureBuilder &builder);

/// \brief Retrieve (or create) a nested type with a known typealias.
PotentialArchetype *getNestedType(TypeAliasDecl *typealias,
/// \brief Retrieve (or create) a nested type with a known concrete type
/// declaration.
PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
GenericSignatureBuilder &builder);

/// Describes the kind of update that is performed.
Expand Down Expand Up @@ -1581,7 +1588,7 @@ class GenericSignatureBuilder::PotentialArchetype {
/// type or typealias of the given protocol, unless the \c kind implies that
/// a potential archetype should not be created if it's missing.
PotentialArchetype *updateNestedTypeForConformance(
PointerUnion<AssociatedTypeDecl *, TypeAliasDecl *> type,
PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
NestedTypeUpdate kind);

/// Update the named nested type when we know this type conforms to the given
Expand Down
41 changes: 41 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2067,6 +2067,47 @@ Type TypeDecl::getDeclaredInterfaceType() const {
return interfaceType->castTo<MetatypeType>()->getInstanceType();
}

int TypeDecl::compare(const TypeDecl *type1, const TypeDecl *type2) {
// Order based on the enclosing declaration.
auto dc1 = type1->getDeclContext();
auto dc2 = type2->getDeclContext();

// Prefer lower depths.
auto depth1 = dc1->getSemanticDepth();
auto depth2 = dc2->getSemanticDepth();
if (depth1 != depth2)
return depth1 < depth2 ? -1 : +1;

// Prefer module names earlier in the alphabet.
if (dc1->isModuleScopeContext() && dc2->isModuleScopeContext()) {
auto module1 = dc1->getParentModule();
auto module2 = dc2->getParentModule();
if (int result = module1->getName().str().compare(module2->getName().str()))
return result;
}

auto nominal1 = dc1->getAsNominalTypeOrNominalTypeExtensionContext();
auto nominal2 = dc2->getAsNominalTypeOrNominalTypeExtensionContext();
if (static_cast<bool>(nominal1) != static_cast<bool>(nominal2)) {
return static_cast<bool>(nominal1) ? -1 : +1;
}
if (nominal1 && nominal2) {
if (int result = compare(nominal1, nominal2))
return result;
}

if (int result = type1->getBaseName().getIdentifier().str().compare(
type2->getBaseName().getIdentifier().str()))
return result;

// Error case: two type declarations that cannot be distinguished.
if (type1 < type2)
return -1;
if (type1 > type2)
return +1;
return 0;
}

bool NominalTypeDecl::hasFixedLayout() const {
// Private and (unversioned) internal types always have a
// fixed layout.
Expand Down
24 changes: 24 additions & 0 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,30 @@ DeclContext::isCascadingContextForLookup(bool functionsAreNonCascading) const {
return getParent()->isCascadingContextForLookup(true);
}

unsigned DeclContext::getSyntacticDepth() const {
// Module scope == depth 0.
if (isModuleScopeContext())
return 0;

return 1 + getParent()->getSyntacticDepth();
}

unsigned DeclContext::getSemanticDepth() const {
// For extensions, count the depth of the nominal type being extended.
if (auto ext = dyn_cast<ExtensionDecl>(this)) {
if (auto nominal = getAsNominalTypeOrNominalTypeExtensionContext())
return nominal->getSemanticDepth();

return 1;
}

// Module scope == depth 0.
if (isModuleScopeContext())
return 0;

return 1 + getParent()->getSemanticDepth();
}

bool DeclContext::walkContext(ASTWalker &Walker) {
switch (getContextKind()) {
case DeclContextKind::Module:
Expand Down
15 changes: 2 additions & 13 deletions lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,6 @@ GenericEnvironment::GenericEnvironment(GenericSignature *signature,
Type());
}

/// Compute the depth of the \c DeclContext chain.
static unsigned declContextDepth(const DeclContext *dc) {
unsigned depth = 0;
while (auto parentDC = dc->getParent()) {
++depth;
dc = parentDC;
}

return depth;
}

void GenericEnvironment::setOwningDeclContext(DeclContext *newOwningDC) {
if (!OwningDC) {
OwningDC = newOwningDC;
Expand All @@ -54,8 +43,8 @@ void GenericEnvironment::setOwningDeclContext(DeclContext *newOwningDC) {
return;

// Find the least common ancestor context to be the owner.
unsigned oldDepth = declContextDepth(OwningDC);
unsigned newDepth = declContextDepth(newOwningDC);
unsigned oldDepth = OwningDC->getSyntacticDepth();
unsigned newDepth = newOwningDC->getSyntacticDepth();

while (oldDepth > newDepth) {
OwningDC = OwningDC->getParent();
Expand Down
Loading