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) {
|
||||
Type t(this);
|
||||
while (t) {
|
||||
auto *derivedClass = dyn_cast_or_null<ClassDecl>(t->getAnyNominal());
|
||||
assert(derivedClass && "expected a class here");
|
||||
// If we have a class-constrained archetype or class-constrained
|
||||
// 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;
|
||||
|
||||
t = t->getSuperclass(resolver);
|
||||
@@ -3139,19 +3148,10 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
|
||||
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.
|
||||
LazyResolver *resolver = dc->getASTContext().getLazyResolver();
|
||||
|
||||
// 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();
|
||||
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
|
||||
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
|
||||
|
||||
@@ -3030,8 +3030,6 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
|
||||
// derived class as the parent type.
|
||||
if (auto *ownerClass = member->getDeclContext()
|
||||
->getAsClassOrClassExtensionContext()) {
|
||||
if (auto *archetypeTy = baseTy->getAs<ArchetypeType>())
|
||||
baseTy = archetypeTy->getSuperclass();
|
||||
baseTy = baseTy->getSuperclassForDecl(ownerClass, this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user