mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Update TypeBase::getSuperclassForDecl() for subclass existentials
This function takes a member of a class and a base type, and returns the correct 'self' type to substitute into the member's type. When accessing a member of a subclass existential, if the member was found via the superclass constraint, we have to erase the existential down to the class type to calculate the member's substituted type. We already had special logic to handle class-constrained archetypes in the callers of getSuperclassForDecl(); move this check into the method, and add a similar check for subclass existentials, which now support the getSuperclass() method.
This commit is contained in:
@@ -3105,10 +3105,19 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
|
|||||||
LazyResolver *resolver) {
|
LazyResolver *resolver) {
|
||||||
Type t(this);
|
Type t(this);
|
||||||
while (t) {
|
while (t) {
|
||||||
auto *derivedClass = dyn_cast_or_null<ClassDecl>(t->getAnyNominal());
|
// If we have a class-constrained archetype or class-constrained
|
||||||
assert(derivedClass && "expected a class here");
|
// existential, get the underlying superclass constraint.
|
||||||
|
auto *nominalDecl = t->getAnyNominal();
|
||||||
|
if (!nominalDecl) {
|
||||||
|
assert(t->is<ArchetypeType>() || t->isExistentialType() &&
|
||||||
|
"expected a class, archetype or existentiall");
|
||||||
|
t = t->getSuperclass(resolver);
|
||||||
|
assert(t && "archetype or existential is not class constrained");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert(isa<ClassDecl>(nominalDecl) && "expected a class here");
|
||||||
|
|
||||||
if (derivedClass == baseClass)
|
if (nominalDecl == baseClass)
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
t = t->getSuperclass(resolver);
|
t = t->getSuperclass(resolver);
|
||||||
@@ -3139,19 +3148,10 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
|
|||||||
return substitutions;
|
return substitutions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found a member of a concrete type from a protocol extension,
|
|
||||||
// get the superclass out of the archetype.
|
|
||||||
if (auto *archetypeTy = baseTy->getAs<ArchetypeType>())
|
|
||||||
baseTy = archetypeTy->getSuperclass();
|
|
||||||
|
|
||||||
// Extract the lazy resolver.
|
// Extract the lazy resolver.
|
||||||
LazyResolver *resolver = dc->getASTContext().getLazyResolver();
|
LazyResolver *resolver = dc->getASTContext().getLazyResolver();
|
||||||
|
|
||||||
// Find the superclass type with the context matching that of the member.
|
// Find the superclass type with the context matching that of the member.
|
||||||
//
|
|
||||||
// FIXME: Do this in the caller?
|
|
||||||
assert(baseTy->getAnyNominal());
|
|
||||||
|
|
||||||
auto *ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
|
auto *ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||||
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
|
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
|
||||||
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
|
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
|
||||||
|
|||||||
@@ -3030,8 +3030,6 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
|
|||||||
// derived class as the parent type.
|
// derived class as the parent type.
|
||||||
if (auto *ownerClass = member->getDeclContext()
|
if (auto *ownerClass = member->getDeclContext()
|
||||||
->getAsClassOrClassExtensionContext()) {
|
->getAsClassOrClassExtensionContext()) {
|
||||||
if (auto *archetypeTy = baseTy->getAs<ArchetypeType>())
|
|
||||||
baseTy = archetypeTy->getSuperclass();
|
|
||||||
baseTy = baseTy->getSuperclassForDecl(ownerClass, this);
|
baseTy = baseTy->getSuperclassForDecl(ownerClass, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user