diff --git a/lib/AST/TypeSubstitution.cpp b/lib/AST/TypeSubstitution.cpp index 0ca775eb083c0..092e4b0377e61 100644 --- a/lib/AST/TypeSubstitution.cpp +++ b/lib/AST/TypeSubstitution.cpp @@ -517,14 +517,20 @@ Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass, t = t->getSuperclass(useArchetypes); } -#ifndef NDEBUG - auto *currentClass = getConcreteTypeForSuperclassTraversing(this) - ->getClassOrBoundGenericClass(); - assert(baseClass->isSuperclassOf(currentClass) && - "no inheritance relationship between given classes"); -#endif - - return ErrorType::get(this); + if (CONDITIONAL_ASSERT_enabled()) { + auto *currentClass = getConcreteTypeForSuperclassTraversing(this) + ->getClassOrBoundGenericClass(); + ASSERT(baseClass->isSuperclassOf(currentClass) && + "no inheritance relationship between given classes"); + } + + // We can end up here if the AST is invalid, because then + // getSuperclassDecl() might resolve to a decl, and yet + // getSuperclass() is just an ErrorType. Make sure we still + // return a nominal type as the result though, and not an + // ErrorType, because that's what callers expect. + return baseClass->getDeclaredInterfaceType() + .subst(SubstitutionMap())->getCanonicalType(); } SubstitutionMap TypeBase::getContextSubstitutionMap() { diff --git a/test/Generics/unify_superclass_types_invalid.swift b/test/Generics/unify_superclass_types_invalid.swift new file mode 100644 index 0000000000000..55e41544b5fdf --- /dev/null +++ b/test/Generics/unify_superclass_types_invalid.swift @@ -0,0 +1,10 @@ +// RUN: %target-typecheck-verify-swift +// RUN: not %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s + +class Base {} +class Derived : Base {} +// expected-error@-1 {{cannot find type 'Foo' in scope}} + +// CHECK-LABEL: unify_superclass_types_invalid.(file).f@ +// CHECK: Generic signature: +func f(_: T) where T: Base, T: Derived {} \ No newline at end of file