Skip to content

Update Sema cast checks for subclass existentials... and more! #8876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/swift/AST/ConcreteDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class ConcreteDeclRef {

/// Retrieve a reference to the declaration this one overrides.
ConcreteDeclRef
getOverriddenDecl(ASTContext &ctx, LazyResolver *resolver) const;
getOverriddenDecl(ASTContext &ctx) const;

/// Determine whether this reference specializes the declaration to which
/// it refers.
Expand Down
6 changes: 2 additions & 4 deletions include/swift/AST/SubstitutionMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ class SubstitutionMap {
static SubstitutionMap
getOverrideSubstitutions(const ValueDecl *baseDecl,
const ValueDecl *derivedDecl,
Optional<SubstitutionMap> derivedSubs,
LazyResolver *resolver);
Optional<SubstitutionMap> derivedSubs);

/// Variant of the above for when we have the generic signatures but not
/// the decls for 'derived' and 'base'.
Expand All @@ -121,8 +120,7 @@ class SubstitutionMap {
const ClassDecl *derivedClass,
GenericSignature *baseSig,
GenericSignature *derivedSig,
Optional<SubstitutionMap> derivedSubs,
LazyResolver *resolver);
Optional<SubstitutionMap> derivedSubs);

/// Combine two substitution maps as follows.
///
Expand Down
20 changes: 6 additions & 14 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -656,18 +656,13 @@ class alignas(1 << TypeAlignInBits) TypeBase {

/// \brief Retrieve the superclass of this type.
///
/// \param resolver The resolver for lazy type checking, or null if the
/// AST is already type-checked.
///
/// \returns The superclass of this type, or a null type if it has no
/// superclass.
Type getSuperclass(LazyResolver *resolver);
Type getSuperclass();

/// \brief True if this type is the exact superclass of another type.
///
/// \param ty The potential subclass.
/// \param resolver The resolver for lazy type checking, or null if the
/// AST is already type-checked.
///
/// \returns True if this type is \c ty or a superclass of \c ty.
///
Expand All @@ -678,7 +673,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
/// will return false. `isBindableToSuperclassOf` should be used
/// for queries that care whether a generic class type can be substituted into
/// a type's subclass.
bool isExactSuperclassOf(Type ty, LazyResolver *resolver);
bool isExactSuperclassOf(Type ty);

/// \brief Get the substituted base class type, starting from a base class
/// declaration and a substituted derived class type.
Expand All @@ -691,23 +686,21 @@ class alignas(1 << TypeAlignInBits) TypeBase {
///
/// Calling `C<String, NSObject>`->getSuperclassForDecl(`A`) will return
/// `A<Int, NSObject>`.
Type getSuperclassForDecl(const ClassDecl *classDecl, LazyResolver *resolver);
Type getSuperclassForDecl(const ClassDecl *classDecl);

/// \brief True if this type is the superclass of another type, or a generic
/// type that could be bound to the superclass.
///
/// \param ty The potential subclass.
/// \param resolver The resolver for lazy type checking, or null if the
/// AST is already type-checked.
///
/// \returns True if this type is \c ty, a superclass of \c ty, or an
/// archetype-parameterized type that can be bound to a superclass
/// of \c ty.
bool isBindableToSuperclassOf(Type ty, LazyResolver *resolver);
bool isBindableToSuperclassOf(Type ty);

/// True if this type contains archetypes that could be substituted with
/// concrete types to form the argument type.
bool isBindableTo(Type ty, LazyResolver *resolver);
bool isBindableTo(Type ty);

/// \brief Determines whether this type is permitted as a method override
/// of the \p other.
Expand Down Expand Up @@ -916,8 +909,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
/// 'self' argument type as appropriate.
Type adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,
const ValueDecl *derivedDecl,
Type memberType,
LazyResolver *resolver);
Type memberType);

/// Return T if this type is Optional<T>; otherwise, return the null type.
Type getOptionalObjectType();
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,7 @@ SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {
CanType Ty = conformance.getConcrete()->getType()->getCanonicalType();

if (Ty != newLookupType) {
assert(Ty->isExactSuperclassOf(newLookupType, nullptr) &&
assert(Ty->isExactSuperclassOf(newLookupType) &&
"Should only create upcasts for sub class.");

// We use the super class as the new look up type.
Expand Down
10 changes: 4 additions & 6 deletions include/swift/SIL/SILType.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,25 +407,23 @@ class SILType {

/// Return the immediate superclass type of this type, or null if
/// it's the most-derived type.
SILType getSuperclass(LazyResolver *resolver) const {
auto superclass = getSwiftRValueType()->getSuperclass(resolver);
SILType getSuperclass() const {
auto superclass = getSwiftRValueType()->getSuperclass();
if (!superclass) return SILType();
return SILType::getPrimitiveObjectType(superclass->getCanonicalType());
}

/// Return true if Ty is a subtype of this exact SILType, or false otherwise.
bool isExactSuperclassOf(SILType Ty) const {
return getSwiftRValueType()->isExactSuperclassOf(Ty.getSwiftRValueType(),
nullptr);
return getSwiftRValueType()->isExactSuperclassOf(Ty.getSwiftRValueType());
}

/// Return true if Ty is a subtype of this SILType, or if this SILType
/// contains archetypes that can be found to form a supertype of Ty, or false
/// otherwise.
bool isBindableToSuperclassOf(SILType Ty) const {
return getSwiftRValueType()->isBindableToSuperclassOf(
Ty.getSwiftRValueType(),
nullptr);
Ty.getSwiftRValueType());
}

/// Transform the function type SILType by replacing all of its interface
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2760,7 +2760,7 @@ class Verifier : public ASTWalker {

// If the destination is a class, walk the supertypes of the source.
if (destTy->getClassOrBoundGenericClass()) {
if (!destTy->isBindableToSuperclassOf(srcTy, nullptr)) {
if (!destTy->isBindableToSuperclassOf(srcTy)) {
srcTy.print(Out);
Out << " is not a superclass of ";
destTy.print(Out);
Expand Down
5 changes: 2 additions & 3 deletions lib/AST/ConcreteDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ ConcreteDeclRef::SpecializedDeclRef::create(
}

ConcreteDeclRef
ConcreteDeclRef::getOverriddenDecl(ASTContext &ctx,
LazyResolver *resolver) const {
ConcreteDeclRef::getOverriddenDecl(ASTContext &ctx) const {
auto *derivedDecl = getDecl();
auto *baseDecl = derivedDecl->getOverriddenDecl();

Expand All @@ -50,7 +49,7 @@ ConcreteDeclRef::getOverriddenDecl(ASTContext &ctx,
if (derivedSig)
derivedSubMap = derivedSig->getSubstitutionMap(getSubstitutions());
auto subMap = SubstitutionMap::getOverrideSubstitutions(
baseDecl, derivedDecl, derivedSubMap, resolver);
baseDecl, derivedDecl, derivedSubMap);
baseSig->getSubstitutions(subMap, subs);
}
return ConcreteDeclRef(ctx, baseDecl, subs);
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/ConformanceLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,9 @@ ProtocolConformance *ConformanceLookupTable::getConformance(

// Find the superclass type that matches where the conformance was
// declared.
Type superclassTy = type->getSuperclass(resolver);
Type superclassTy = type->getSuperclass();
while (superclassTy->getAnyNominal() != conformingNominal)
superclassTy = superclassTy->getSuperclass(resolver);
superclassTy = superclassTy->getSuperclass();

// Look up the inherited conformance.
ModuleDecl *module = entry->getDeclContext()->getParentModule();
Expand Down
7 changes: 3 additions & 4 deletions lib/AST/GenericSignatureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,7 @@ void GenericSignatureBuilder::updateSuperclass(
//
// then the second constraint should be allowed, constraining U to Bar
// and secondarily imposing a T == Int constraint.
if (existingSuperclass->isExactSuperclassOf(superclass, nullptr)) {
if (existingSuperclass->isExactSuperclassOf(superclass)) {
equivClass->superclass = superclass;

// We've strengthened the bound, so update superclass conformances.
Expand Down Expand Up @@ -4428,7 +4428,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
},
[&](Type superclass) {
// If this class is a superclass of the "best"
if (superclass->isExactSuperclassOf(equivClass->superclass, nullptr))
if (superclass->isExactSuperclassOf(equivClass->superclass))
return ConstraintRelation::Redundant;

// Otherwise, it conflicts.
Expand All @@ -4442,8 +4442,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
// FIXME: Substitute into the concrete type.
if (equivClass->concreteType) {
// Make sure the concrete type fulfills the superclass requirement.
if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType,
nullptr)) {
if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType)) {
if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
representativeConstraint.archetype)) {
Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,9 +681,9 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol,
= rootConformance->getType()->getClassOrBoundGenericClass();

// Map up to our superclass's type.
Type superclassTy = type->getSuperclass(resolver);
Type superclassTy = type->getSuperclass();
while (superclassTy->getAnyNominal() != conformingNominal)
superclassTy = superclassTy->getSuperclass(resolver);
superclassTy = superclassTy->getSuperclass();

// Compute the conformance for the inherited type.
auto inheritedConformance = lookupConformance(superclassTy, protocol,
Expand Down
11 changes: 4 additions & 7 deletions lib/AST/SubstitutionMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ SubstitutionMap::getProtocolSubstitutions(ProtocolDecl *protocol,
SubstitutionMap
SubstitutionMap::getOverrideSubstitutions(const ValueDecl *baseDecl,
const ValueDecl *derivedDecl,
Optional<SubstitutionMap> derivedSubs,
LazyResolver *resolver) {
Optional<SubstitutionMap> derivedSubs) {
auto *baseClass = baseDecl->getDeclContext()
->getAsClassOrClassExtensionContext();
auto *derivedClass = derivedDecl->getDeclContext()
Expand All @@ -251,17 +250,15 @@ SubstitutionMap::getOverrideSubstitutions(const ValueDecl *baseDecl,

return getOverrideSubstitutions(baseClass, derivedClass,
baseSig, derivedSig,
derivedSubs,
resolver);
derivedSubs);
}

SubstitutionMap
SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass,
const ClassDecl *derivedClass,
GenericSignature *baseSig,
GenericSignature *derivedSig,
Optional<SubstitutionMap> derivedSubs,
LazyResolver *resolver) {
Optional<SubstitutionMap> derivedSubs) {
if (baseSig == nullptr)
return SubstitutionMap();

Expand All @@ -275,7 +272,7 @@ SubstitutionMap::getOverrideSubstitutions(const ClassDecl *baseClass,
auto derivedClassTy = derivedClass->getDeclaredInterfaceType();
if (derivedSubs)
derivedClassTy = derivedClassTy.subst(*derivedSubs);
auto baseClassTy = derivedClassTy->getSuperclassForDecl(baseClass, resolver);
auto baseClassTy = derivedClassTy->getSuperclassForDecl(baseClass);

baseSubMap = baseClassTy->getContextSubstitutionMap(M, baseClass);
}
Expand Down
35 changes: 15 additions & 20 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@ bool TypeBase::mayHaveSuperclass() {
return is<DynamicSelfType>();
}

Type TypeBase::getSuperclass(LazyResolver *resolver) {
Type TypeBase::getSuperclass() {
auto *nominalDecl = getAnyNominal();
auto *classDecl = dyn_cast_or_null<ClassDecl>(nominalDecl);

Expand Down Expand Up @@ -1604,7 +1604,7 @@ Type TypeBase::getSuperclass(LazyResolver *resolver) {
return superclassTy.subst(subMap);
}

bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) {
bool TypeBase::isExactSuperclassOf(Type ty) {
// For there to be a superclass relationship, we must be a superclass, and
// the potential subtype must be a class or superclass-bounded archetype.
if (!getClassOrBoundGenericClass() || !ty->mayHaveSuperclass())
Expand All @@ -1615,12 +1615,12 @@ bool TypeBase::isExactSuperclassOf(Type ty, LazyResolver *resolver) {
return true;
if (ty->getAnyNominal() && ty->getAnyNominal()->isInvalid())
return false;
} while ((ty = ty->getSuperclass(resolver)));
} while ((ty = ty->getSuperclass()));
return false;
}

/// Returns true if type `a` has archetypes that can be bound to form `b`.
bool TypeBase::isBindableTo(Type b, LazyResolver *resolver) {
bool TypeBase::isBindableTo(Type b) {
class IsBindableVisitor : public TypeVisitor<IsBindableVisitor, bool, CanType>
{
llvm::DenseMap<ArchetypeType *, CanType> Bindings;
Expand Down Expand Up @@ -1845,10 +1845,10 @@ bool TypeBase::isBindableTo(Type b, LazyResolver *resolver) {
b->getCanonicalType());
}

bool TypeBase::isBindableToSuperclassOf(Type ty, LazyResolver *resolver) {
bool TypeBase::isBindableToSuperclassOf(Type ty) {
// Do an exact match if no archetypes are involved.
if (!hasArchetype())
return isExactSuperclassOf(ty, resolver);
return isExactSuperclassOf(ty);

// For there to be a superclass relationship,
// the potential subtype must be a class or superclass-bounded archetype.
Expand All @@ -1865,11 +1865,11 @@ bool TypeBase::isBindableToSuperclassOf(Type ty, LazyResolver *resolver) {
return true;

do {
if (isBindableTo(ty, resolver))
if (isBindableTo(ty))
return true;
if (ty->getAnyNominal() && ty->getAnyNominal()->isInvalid())
return false;
} while ((ty = ty->getSuperclass(resolver)));
} while ((ty = ty->getSuperclass()));
return false;
}

Expand Down Expand Up @@ -2418,7 +2418,7 @@ static bool canOverride(CanType t1, CanType t2,
}

// Class-to-class.
return t2->isExactSuperclassOf(t1, resolver);
return t2->isExactSuperclassOf(t1);
}

bool TypeBase::canOverride(Type other, OverrideMatchMode matchMode,
Expand Down Expand Up @@ -3122,8 +3122,7 @@ Type Type::substDependentTypesWithErrorTypes() const {
SubstFlags::UseErrorType));
}

Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
LazyResolver *resolver) {
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
Type t(this);
while (t) {
// If we have a class-constrained archetype or class-constrained
Expand All @@ -3132,7 +3131,7 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
if (!nominalDecl) {
assert(t->is<ArchetypeType>() || t->isExistentialType() &&
"expected a class, archetype or existential");
t = t->getSuperclass(resolver);
t = t->getSuperclass();
assert(t && "archetype or existential is not class constrained");
continue;
}
Expand All @@ -3141,7 +3140,7 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass,
if (nominalDecl == baseClass)
return t;

t = t->getSuperclass(resolver);
t = t->getSuperclass();
}
llvm_unreachable("no inheritance relationship between given classes");
}
Expand Down Expand Up @@ -3169,13 +3168,10 @@ TypeBase::getContextSubstitutions(const DeclContext *dc,
return substitutions;
}

// Extract the lazy resolver.
LazyResolver *resolver = dc->getASTContext().getLazyResolver();

// Find the superclass type with the context matching that of the member.
auto *ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
if (auto *ownerClass = dyn_cast<ClassDecl>(ownerNominal))
baseTy = baseTy->getSuperclassForDecl(ownerClass, resolver);
baseTy = baseTy->getSuperclassForDecl(ownerClass);

assert(ownerNominal == baseTy->getAnyNominal());

Expand Down Expand Up @@ -3307,10 +3303,9 @@ Type TypeBase::getTypeOfMember(ModuleDecl *module, const ValueDecl *member,

Type TypeBase::adjustSuperclassMemberDeclType(const ValueDecl *baseDecl,
const ValueDecl *derivedDecl,
Type memberType,
LazyResolver *resolver) {
Type memberType) {
auto subs = SubstitutionMap::getOverrideSubstitutions(
baseDecl, derivedDecl, /*derivedSubs=*/None, resolver);
baseDecl, derivedDecl, /*derivedSubs=*/None);

if (auto *genericMemberType = memberType->getAs<GenericFunctionType>()) {
memberType = FunctionType::get(genericMemberType->getInput(),
Expand Down
Loading