Skip to content

Commit 680688c

Browse files
committed
AST: Cleanups for TypeBase::getSuperclass()
First, enforce that the superclass of a class is an interface type. Previously, Swift classes used interface types but imported Objective-C generics used archetypes. When the superclass type is always an interface type, we can use the recently-added gatherAllSubstitutions() instead of rolling our own parent type walk. Also, this exposed an issue in name lookup where we would call getSuperclass() on a type whose parent was an unbound generic. This doesn't make sense, so generalize the existing check there.
1 parent 68c6b1a commit 680688c

File tree

5 files changed

+33
-66
lines changed

5 files changed

+33
-66
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3212,9 +3212,7 @@ class ClassDecl : public NominalTypeDecl {
32123212
ClassDecl *getSuperclassDecl() const;
32133213

32143214
/// Set the superclass of this class.
3215-
void setSuperclass(Type superclass) {
3216-
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
3217-
}
3215+
void setSuperclass(Type superclass);
32183216

32193217
/// Retrieve the status of circularity checking for class inheritance.
32203218
CircularityCheck getCircularityCheck() const {

lib/AST/Decl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4762,3 +4762,9 @@ ClassDecl *ClassDecl::getSuperclassDecl() const {
47624762
return superclass->getClassOrBoundGenericClass();
47634763
return nullptr;
47644764
}
4765+
4766+
void ClassDecl::setSuperclass(Type superclass) {
4767+
assert((!superclass || !superclass->hasArchetype())
4768+
&& "superclass must be interface type");
4769+
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
4770+
}

lib/AST/LookupVisibleDecls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ class OverrideFilteringConsumer : public VisibleDeclConsumer {
716716
}
717717

718718
// Does it make sense to substitute types?
719-
bool shouldSubst = !isa<UnboundGenericType>(BaseTy.getPointer()) &&
719+
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
720720
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
721721
!BaseTy->isAnyExistentialType();
722722
ModuleDecl *M = DC->getParentModule();

lib/AST/Type.cpp

Lines changed: 23 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,76 +1597,37 @@ bool TypeBase::isSpelledLike(Type other) {
15971597
}
15981598

15991599
Type TypeBase::getSuperclass(LazyResolver *resolver) {
1600-
// If this type is either a bound generic type, or a nested type inside a
1601-
// bound generic type, we will need to fish out the generic parameters.
1602-
Type specializedTy;
1603-
1604-
ClassDecl *classDecl;
1605-
if (auto classTy = getAs<ClassType>()) {
1606-
classDecl = classTy->getDecl();
1607-
if (auto parentTy = classTy->getParent()) {
1608-
if (parentTy->isSpecialized())
1609-
specializedTy = parentTy;
1610-
}
1611-
} else if (auto boundTy = getAs<BoundGenericType>()) {
1612-
classDecl = dyn_cast<ClassDecl>(boundTy->getDecl());
1613-
specializedTy = this;
1614-
} else if (auto archetype = getAs<ArchetypeType>()) {
1615-
return archetype->getSuperclass();
1616-
} else if (auto dynamicSelfTy = getAs<DynamicSelfType>()) {
1617-
return dynamicSelfTy->getSelfType();
1618-
} else {
1619-
// No other types have superclasses.
1620-
return nullptr;
1621-
}
1600+
ClassDecl *classDecl = getClassOrBoundGenericClass();
16221601

1623-
// Get the superclass type. If the class is generic, the superclass type may
1624-
// contain generic type parameters from the signature of the class.
1625-
Type superclassTy;
1626-
if (classDecl)
1627-
superclassTy = classDecl->getSuperclass();
1602+
// Handle some special non-class types here.
1603+
if (!classDecl) {
1604+
if (auto archetype = getAs<ArchetypeType>())
1605+
return archetype->getSuperclass();
16281606

1629-
// If there's no superclass, return a null type. If the class is not in a
1630-
// generic context, return the original superclass type.
1631-
if (!superclassTy || !classDecl->isGenericContext())
1632-
return superclassTy;
1607+
if (auto dynamicSelfTy = getAs<DynamicSelfType>())
1608+
return dynamicSelfTy->getSelfType();
16331609

1634-
// The class is defined in a generic context, so its superclass type may refer
1635-
// to generic parameters of the class or some parent type of the class. Map
1636-
// it to a contextual type.
1610+
// No other types have superclasses.
1611+
return nullptr;
1612+
}
16371613

1638-
// FIXME: Lame to rely on archetypes in the substitution below.
1639-
superclassTy = ArchetypeBuilder::mapTypeIntoContext(classDecl, superclassTy);
1614+
// We have a class, so get the superclass type.
1615+
//
1616+
// If the derived class is generic, the superclass type may contain
1617+
// generic type parameters from the signature of the derived class.
1618+
Type superclassTy = classDecl->getSuperclass();
16401619

1641-
// If the type does not bind any generic parameters, return the superclass
1642-
// type as-is.
1643-
if (!specializedTy)
1620+
// If there's no superclass, or it is fully concrete, we're done.
1621+
if (!superclassTy || !superclassTy->hasTypeParameter())
16441622
return superclassTy;
16451623

1646-
// If the type is specialized, we need to gather all of the substitutions
1647-
// for the type and any parent types.
1648-
TypeSubstitutionMap substitutions;
1649-
while (specializedTy) {
1650-
if (auto nominalTy = specializedTy->getAs<NominalType>()) {
1651-
specializedTy = nominalTy->getParent();
1652-
continue;
1653-
}
1654-
1655-
// Introduce substitutions for each of the generic parameters/arguments.
1656-
auto boundTy = specializedTy->castTo<BoundGenericType>();
1657-
auto gp = boundTy->getDecl()->getGenericParams()->getParams();
1658-
for (unsigned i = 0, n = boundTy->getGenericArgs().size(); i != n; ++i) {
1659-
auto archetype = gp[i]->getArchetype();
1660-
substitutions[archetype] = boundTy->getGenericArgs()[i];
1661-
}
1662-
1663-
specializedTy = boundTy->getParent();
1664-
}
1665-
1666-
// Perform substitutions into the superclass type to yield the
1667-
// substituted superclass type.
1624+
// Gather substitutions from the self type, and apply them to the original
1625+
// superclass type to form the substituted superclass type.
16681626
Module *module = classDecl->getModuleContext();
1669-
return superclassTy.subst(module, substitutions, None);
1627+
auto *sig = classDecl->getGenericSignatureOfContext();
1628+
auto subs = sig->getSubstitutionMap(gatherAllSubstitutions(module, resolver));
1629+
1630+
return superclassTy.subst(module, subs, None);
16701631
}
16711632

16721633
bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,6 +5740,8 @@ namespace {
57405740
isInSystemModule(dc),
57415741
/*isFullyBridgeable*/false);
57425742
if (superclassType) {
5743+
superclassType =
5744+
ArchetypeBuilder::mapTypeOutOfContext(result, superclassType);
57435745
assert(superclassType->is<ClassType>() ||
57445746
superclassType->is<BoundGenericClassType>());
57455747
inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType));

0 commit comments

Comments
 (0)