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;
|
ClassDecl *getSuperclassDecl() const;
|
||||||
|
|
||||||
/// Set the superclass of this class.
|
/// Set the superclass of this class.
|
||||||
void setSuperclass(Type superclass) {
|
void setSuperclass(Type superclass);
|
||||||
LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve the status of circularity checking for class inheritance.
|
/// Retrieve the status of circularity checking for class inheritance.
|
||||||
CircularityCheck getCircularityCheck() const {
|
CircularityCheck getCircularityCheck() const {
|
||||||
|
|||||||
@@ -4762,3 +4762,9 @@ ClassDecl *ClassDecl::getSuperclassDecl() const {
|
|||||||
return superclass->getClassOrBoundGenericClass();
|
return superclass->getClassOrBoundGenericClass();
|
||||||
return nullptr;
|
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?
|
// Does it make sense to substitute types?
|
||||||
bool shouldSubst = !isa<UnboundGenericType>(BaseTy.getPointer()) &&
|
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
|
||||||
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
|
!isa<AnyMetatypeType>(BaseTy.getPointer()) &&
|
||||||
!BaseTy->isAnyExistentialType();
|
!BaseTy->isAnyExistentialType();
|
||||||
ModuleDecl *M = DC->getParentModule();
|
ModuleDecl *M = DC->getParentModule();
|
||||||
|
|||||||
@@ -1597,76 +1597,37 @@ bool TypeBase::isSpelledLike(Type other) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type TypeBase::getSuperclass(LazyResolver *resolver) {
|
Type TypeBase::getSuperclass(LazyResolver *resolver) {
|
||||||
// If this type is either a bound generic type, or a nested type inside a
|
ClassDecl *classDecl = getClassOrBoundGenericClass();
|
||||||
// bound generic type, we will need to fish out the generic parameters.
|
|
||||||
Type specializedTy;
|
|
||||||
|
|
||||||
ClassDecl *classDecl;
|
// Handle some special non-class types here.
|
||||||
if (auto classTy = getAs<ClassType>()) {
|
if (!classDecl) {
|
||||||
classDecl = classTy->getDecl();
|
if (auto archetype = getAs<ArchetypeType>())
|
||||||
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();
|
return archetype->getSuperclass();
|
||||||
} else if (auto dynamicSelfTy = getAs<DynamicSelfType>()) {
|
|
||||||
|
if (auto dynamicSelfTy = getAs<DynamicSelfType>())
|
||||||
return dynamicSelfTy->getSelfType();
|
return dynamicSelfTy->getSelfType();
|
||||||
} else {
|
|
||||||
// No other types have superclasses.
|
// No other types have superclasses.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the superclass type. If the class is generic, the superclass type may
|
// We have a class, so get the superclass type.
|
||||||
// contain generic type parameters from the signature of the class.
|
//
|
||||||
Type superclassTy;
|
// If the derived class is generic, the superclass type may contain
|
||||||
if (classDecl)
|
// generic type parameters from the signature of the derived class.
|
||||||
superclassTy = classDecl->getSuperclass();
|
Type superclassTy = classDecl->getSuperclass();
|
||||||
|
|
||||||
// If there's no superclass, return a null type. If the class is not in a
|
// If there's no superclass, or it is fully concrete, we're done.
|
||||||
// generic context, return the original superclass type.
|
if (!superclassTy || !superclassTy->hasTypeParameter())
|
||||||
if (!superclassTy || !classDecl->isGenericContext())
|
|
||||||
return superclassTy;
|
return superclassTy;
|
||||||
|
|
||||||
// The class is defined in a generic context, so its superclass type may refer
|
// Gather substitutions from the self type, and apply them to the original
|
||||||
// to generic parameters of the class or some parent type of the class. Map
|
// superclass type to form the substituted superclass type.
|
||||||
// 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.
|
|
||||||
Module *module = classDecl->getModuleContext();
|
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) {
|
bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) {
|
||||||
|
|||||||
@@ -5740,6 +5740,8 @@ namespace {
|
|||||||
isInSystemModule(dc),
|
isInSystemModule(dc),
|
||||||
/*isFullyBridgeable*/false);
|
/*isFullyBridgeable*/false);
|
||||||
if (superclassType) {
|
if (superclassType) {
|
||||||
|
superclassType =
|
||||||
|
ArchetypeBuilder::mapTypeOutOfContext(result, superclassType);
|
||||||
assert(superclassType->is<ClassType>() ||
|
assert(superclassType->is<ClassType>() ||
|
||||||
superclassType->is<BoundGenericClassType>());
|
superclassType->is<BoundGenericClassType>());
|
||||||
inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType));
|
inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType));
|
||||||
|
|||||||
Reference in New Issue
Block a user