mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Fix a couple of crash-on-invalid problems with class inheritance
It is possible for ClassDecl::getSuperclassDecl() to succeed but for ClassDecl::getSuperclass() to fail. This happens if the superclass is a generic type and one of the generic arguments could not be resolved, or does not satisfy the generic requirements, for example; in that case, a BoundGenericType cannot be formed. In a couple of places we were not prepared for this possibility. Let's recover by making judicious use of ErrorType. Fixes <rdar://problem/73169149>.
This commit is contained in:
@@ -62,6 +62,12 @@ Expr *swift::buildSelfReference(VarDecl *selfDecl,
|
|||||||
selfTy = metaTy->getInstanceType();
|
selfTy = metaTy->getInstanceType();
|
||||||
}
|
}
|
||||||
selfTy = selfTy->getSuperclass();
|
selfTy = selfTy->getSuperclass();
|
||||||
|
if (!selfTy) {
|
||||||
|
// Error recovery path. We end up here if getSuperclassDecl() succeeds
|
||||||
|
// but getSuperclass() fails (because, for instance, a generic parameter
|
||||||
|
// of a generic nominal type cannot be resolved).
|
||||||
|
selfTy = ErrorType::get(ctx);
|
||||||
|
}
|
||||||
if (isMetatype)
|
if (isMetatype)
|
||||||
selfTy = MetatypeType::get(selfTy);
|
selfTy = MetatypeType::get(selfTy);
|
||||||
|
|
||||||
@@ -70,7 +76,7 @@ Expr *swift::buildSelfReference(VarDecl *selfDecl,
|
|||||||
|
|
||||||
// If no conversion type was specified, or we're already at that type, we're
|
// If no conversion type was specified, or we're already at that type, we're
|
||||||
// done.
|
// done.
|
||||||
if (!convertTy || convertTy->isEqual(selfTy))
|
if (!convertTy || convertTy->isEqual(selfTy) || selfTy->is<ErrorType>())
|
||||||
return superRef;
|
return superRef;
|
||||||
|
|
||||||
// Insert the appropriate expr to handle the upcast.
|
// Insert the appropriate expr to handle the upcast.
|
||||||
|
|||||||
@@ -151,12 +151,12 @@ namespace {
|
|||||||
auto conformance = DC->getParentModule()->lookupConformance(
|
auto conformance = DC->getParentModule()->lookupConformance(
|
||||||
conformingType, foundProto);
|
conformingType, foundProto);
|
||||||
if (conformance.isInvalid()) {
|
if (conformance.isInvalid()) {
|
||||||
// If there's no conformance, we have an existential
|
if (foundInType->isExistentialType()) {
|
||||||
// and we found a member from one of the protocols, and
|
// If there's no conformance, we have an existential
|
||||||
// not a class constraint if any.
|
// and we found a member from one of the protocols, and
|
||||||
assert(foundInType->isExistentialType() || foundInType->hasError());
|
// not a class constraint if any.
|
||||||
if (foundInType->isExistentialType())
|
|
||||||
addResult(found);
|
addResult(found);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -717,10 +717,16 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
|
|||||||
// Adjust the self type of the access to refer to the relevant superclass.
|
// Adjust the self type of the access to refer to the relevant superclass.
|
||||||
auto *baseClass = override->getDeclContext()->getSelfClassDecl();
|
auto *baseClass = override->getDeclContext()->getSelfClassDecl();
|
||||||
selfTypeForAccess = selfTypeForAccess->getSuperclassForDecl(baseClass);
|
selfTypeForAccess = selfTypeForAccess->getSuperclassForDecl(baseClass);
|
||||||
subs =
|
|
||||||
selfTypeForAccess->getContextSubstitutionMap(
|
// Error recovery path. We get an ErrorType here if getSuperclassForDecl()
|
||||||
accessor->getParentModule(),
|
// fails (because, for instance, a generic parameter of a generic nominal
|
||||||
baseClass);
|
// type cannot be resolved).
|
||||||
|
if (!selfTypeForAccess->is<ErrorType>()) {
|
||||||
|
subs =
|
||||||
|
selfTypeForAccess->getContextSubstitutionMap(
|
||||||
|
accessor->getParentModule(),
|
||||||
|
baseClass);
|
||||||
|
}
|
||||||
|
|
||||||
storage = override;
|
storage = override;
|
||||||
|
|
||||||
|
|||||||
26
validation-test/compiler_crashers_2_fixed/rdar73169149.swift
Normal file
26
validation-test/compiler_crashers_2_fixed/rdar73169149.swift
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// RUN: not %target-swift-frontend -emit-ir %s
|
||||||
|
|
||||||
|
public protocol Ungulate {
|
||||||
|
func eat()
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Horse<T> : Ungulate {
|
||||||
|
public var saddle: AnyObject? = nil
|
||||||
|
|
||||||
|
public func eat() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Hay {}
|
||||||
|
|
||||||
|
// Here, ClassDecl::getSuperclassDecl() will find the 'Horse' class, but
|
||||||
|
// ClassDecl::getSuperclass() will return ErrorType because the generic
|
||||||
|
// argument 'DoesNotExist' cannot be resolved.
|
||||||
|
public class Pony : Horse<DoesNotExist> {
|
||||||
|
public override var saddle: AnyObject? {
|
||||||
|
didSet {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func eat(_: Hay) {
|
||||||
|
eat()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user