Skip to content

Commit bee9fee

Browse files
committed
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>.
1 parent bc85d66 commit bee9fee

File tree

2 files changed

+26
-13
lines changed

2 files changed

+26
-13
lines changed

lib/AST/RequirementMachine/ConcreteContraction.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -624,19 +624,26 @@ bool ConcreteContraction::performConcreteContraction(
624624

625625
auto superclassTy = *found->second.begin();
626626

627-
for (const auto *proto : pair.second) {
628-
if (auto otherSuperclassTy = proto->getSuperclass()) {
629-
if (Debug) {
630-
llvm::dbgs() << "@ Subject type of superclass requirement "
631-
<< subjectType << " : " << superclassTy
632-
<< " conforms to "<< proto->getName()
633-
<< " which has a superclass bound "
634-
<< otherSuperclassTy << "\n";
635-
}
636-
637-
if (superclassTy->isEqual(otherSuperclassTy)) {
638-
Superclasses.erase(subjectType);
639-
break;
627+
for (auto *proto : pair.second) {
628+
auto *module = proto->getParentModule();
629+
if (module->lookupConformance(superclassTy, proto)) {
630+
auto genericSig = proto->getGenericSignature();
631+
// FIXME: If we end up here while building the requirement
632+
// signature of `proto`, we will hit a request cycle.
633+
if (auto otherSuperclassTy = genericSig->getSuperclassBound(
634+
proto->getSelfInterfaceType())) {
635+
if (Debug) {
636+
llvm::dbgs() << "@ Subject type of superclass requirement "
637+
<< subjectType << " : " << superclassTy
638+
<< " conforms to "<< proto->getName()
639+
<< " which has a superclass bound "
640+
<< otherSuperclassTy << "\n";
641+
}
642+
643+
if (superclassTy->isEqual(otherSuperclassTy)) {
644+
Superclasses.erase(subjectType);
645+
break;
646+
}
640647
}
641648
}
642649
}

test/Generics/protocol_superclass_cycle.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ func foo5<T : SubSuperP>(_: T) {}
5252
// CHECK-NEXT: Generic signature: <T where T : Q, T.[Q]T : SubSuperP>
5353
func foo6<T : Q>(_: T) where T.T : SubSuperP {}
5454

55+
protocol POther where Self : COther {}
56+
class COther : POther {}
57+
58+
// CHECK-LABEL: .foo7@
59+
// CHECK-NEXT: Generic signature: <T where T : POther>
60+
func foo7<T>(_: T) where T : COther, T : POther {}

0 commit comments

Comments
 (0)