RequirementMachine: Don't call ProtocolDecl::getSuperclass() in concrete contraction

This changes the minimized signature in a very narrow edge case.

If you have

    class C : P {}

and also

    protocol P : C {}
    protocol P where Self : C {}

then <T where T : P, T : C> now becomes <T : P> both with spellings;
before, the first one gave <T : P> and the second <T : C>.
This commit is contained in:
Slava Pestov
2024-03-20 15:32:58 -04:00
parent bc85d66b96
commit bee9fee58b
2 changed files with 25 additions and 12 deletions

View File

@@ -624,19 +624,26 @@ bool ConcreteContraction::performConcreteContraction(
auto superclassTy = *found->second.begin();
for (const auto *proto : pair.second) {
if (auto otherSuperclassTy = proto->getSuperclass()) {
if (Debug) {
llvm::dbgs() << "@ Subject type of superclass requirement "
<< subjectType << " : " << superclassTy
<< " conforms to "<< proto->getName()
<< " which has a superclass bound "
<< otherSuperclassTy << "\n";
}
for (auto *proto : pair.second) {
auto *module = proto->getParentModule();
if (module->lookupConformance(superclassTy, proto)) {
auto genericSig = proto->getGenericSignature();
// FIXME: If we end up here while building the requirement
// signature of `proto`, we will hit a request cycle.
if (auto otherSuperclassTy = genericSig->getSuperclassBound(
proto->getSelfInterfaceType())) {
if (Debug) {
llvm::dbgs() << "@ Subject type of superclass requirement "
<< subjectType << " : " << superclassTy
<< " conforms to "<< proto->getName()
<< " which has a superclass bound "
<< otherSuperclassTy << "\n";
}
if (superclassTy->isEqual(otherSuperclassTy)) {
Superclasses.erase(subjectType);
break;
if (superclassTy->isEqual(otherSuperclassTy)) {
Superclasses.erase(subjectType);
break;
}
}
}
}

View File

@@ -52,3 +52,9 @@ func foo5<T : SubSuperP>(_: T) {}
// CHECK-NEXT: Generic signature: <T where T : Q, T.[Q]T : SubSuperP>
func foo6<T : Q>(_: T) where T.T : SubSuperP {}
protocol POther where Self : COther {}
class COther : POther {}
// CHECK-LABEL: .foo7@
// CHECK-NEXT: Generic signature: <T where T : POther>
func foo7<T>(_: T) where T : COther, T : POther {}