mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -3212,9 +3212,7 @@ public:
|
||||
ClassDecl *getSuperclassDecl() const;
|
||||
|
||||
/// Set the superclass of this class.
|
||||
void setSuperclass(Type superclass) {
|
||||
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
|
||||
}
|
||||
void setSuperclass(Type superclass);
|
||||
|
||||
/// Retrieve the status of circularity checking for class inheritance.
|
||||
CircularityCheck getCircularityCheck() const {
|
||||
|
||||
@@ -4762,3 +4762,9 @@ ClassDecl *ClassDecl::getSuperclassDecl() const {
|
||||
return superclass->getClassOrBoundGenericClass();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClassDecl::setSuperclass(Type superclass) {
|
||||
assert((!superclass || !superclass->hasArchetype())
|
||||
&& "superclass must be interface type");
|
||||
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
|
||||
}
|
||||
|
||||
@@ -716,7 +716,7 @@ public:
|
||||
}
|
||||
|
||||
// Does it make sense to substitute types?
|
||||
bool shouldSubst = !isa<UnboundGenericType>(BaseTy.getPointer()) &&
|
||||
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
|
||||
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
|
||||
!BaseTy->isAnyExistentialType();
|
||||
ModuleDecl *M = DC->getParentModule();
|
||||
|
||||
@@ -1597,76 +1597,37 @@ bool TypeBase::isSpelledLike(Type other) {
|
||||
}
|
||||
|
||||
Type TypeBase::getSuperclass(LazyResolver *resolver) {
|
||||
// If this type is either a bound generic type, or a nested type inside a
|
||||
// bound generic type, we will need to fish out the generic parameters.
|
||||
Type specializedTy;
|
||||
ClassDecl *classDecl = getClassOrBoundGenericClass();
|
||||
|
||||
// Handle some special non-class types here.
|
||||
if (!classDecl) {
|
||||
if (auto archetype = getAs<ArchetypeType>())
|
||||
return archetype->getSuperclass();
|
||||
|
||||
if (auto dynamicSelfTy = getAs<DynamicSelfType>())
|
||||
return dynamicSelfTy->getSelfType();
|
||||
|
||||
ClassDecl *classDecl;
|
||||
if (auto classTy = getAs<ClassType>()) {
|
||||
classDecl = classTy->getDecl();
|
||||
if (auto parentTy = classTy->getParent()) {
|
||||
if (parentTy->isSpecialized())
|
||||
specializedTy = parentTy;
|
||||
}
|
||||
} else if (auto boundTy = getAs<BoundGenericType>()) {
|
||||
classDecl = dyn_cast<ClassDecl>(boundTy->getDecl());
|
||||
specializedTy = this;
|
||||
} else if (auto archetype = getAs<ArchetypeType>()) {
|
||||
return archetype->getSuperclass();
|
||||
} else if (auto dynamicSelfTy = getAs<DynamicSelfType>()) {
|
||||
return dynamicSelfTy->getSelfType();
|
||||
} else {
|
||||
// No other types have superclasses.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the superclass type. If the class is generic, the superclass type may
|
||||
// contain generic type parameters from the signature of the class.
|
||||
Type superclassTy;
|
||||
if (classDecl)
|
||||
superclassTy = classDecl->getSuperclass();
|
||||
// We have a class, so get the superclass type.
|
||||
//
|
||||
// If the derived class is generic, the superclass type may contain
|
||||
// generic type parameters from the signature of the derived class.
|
||||
Type superclassTy = classDecl->getSuperclass();
|
||||
|
||||
// If there's no superclass, return a null type. If the class is not in a
|
||||
// generic context, return the original superclass type.
|
||||
if (!superclassTy || !classDecl->isGenericContext())
|
||||
// If there's no superclass, or it is fully concrete, we're done.
|
||||
if (!superclassTy || !superclassTy->hasTypeParameter())
|
||||
return superclassTy;
|
||||
|
||||
// The class is defined in a generic context, so its superclass type may refer
|
||||
// to generic parameters of the class or some parent type of the class. Map
|
||||
// it to a contextual type.
|
||||
|
||||
// FIXME: Lame to rely on archetypes in the substitution below.
|
||||
superclassTy = ArchetypeBuilder::mapTypeIntoContext(classDecl, superclassTy);
|
||||
|
||||
// If the type does not bind any generic parameters, return the superclass
|
||||
// type as-is.
|
||||
if (!specializedTy)
|
||||
return superclassTy;
|
||||
|
||||
// If the type is specialized, we need to gather all of the substitutions
|
||||
// for the type and any parent types.
|
||||
TypeSubstitutionMap substitutions;
|
||||
while (specializedTy) {
|
||||
if (auto nominalTy = specializedTy->getAs<NominalType>()) {
|
||||
specializedTy = nominalTy->getParent();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Introduce substitutions for each of the generic parameters/arguments.
|
||||
auto boundTy = specializedTy->castTo<BoundGenericType>();
|
||||
auto gp = boundTy->getDecl()->getGenericParams()->getParams();
|
||||
for (unsigned i = 0, n = boundTy->getGenericArgs().size(); i != n; ++i) {
|
||||
auto archetype = gp[i]->getArchetype();
|
||||
substitutions[archetype] = boundTy->getGenericArgs()[i];
|
||||
}
|
||||
|
||||
specializedTy = boundTy->getParent();
|
||||
}
|
||||
|
||||
// Perform substitutions into the superclass type to yield the
|
||||
// substituted superclass type.
|
||||
// Gather substitutions from the self type, and apply them to the original
|
||||
// superclass type to form the substituted superclass type.
|
||||
Module *module = classDecl->getModuleContext();
|
||||
return superclassTy.subst(module, substitutions, None);
|
||||
auto *sig = classDecl->getGenericSignatureOfContext();
|
||||
auto subs = sig->getSubstitutionMap(gatherAllSubstitutions(module, resolver));
|
||||
|
||||
return superclassTy.subst(module, subs, None);
|
||||
}
|
||||
|
||||
bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) {
|
||||
|
||||
@@ -5740,6 +5740,8 @@ namespace {
|
||||
isInSystemModule(dc),
|
||||
/*isFullyBridgeable*/false);
|
||||
if (superclassType) {
|
||||
superclassType =
|
||||
ArchetypeBuilder::mapTypeOutOfContext(result, superclassType);
|
||||
assert(superclassType->is<ClassType>() ||
|
||||
superclassType->is<BoundGenericClassType>());
|
||||
inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType));
|
||||
|
||||
Reference in New Issue
Block a user