Sema: ext's must add solo invertible conformances

This helps prevent confusion after not inferring requirements if the
extension adds a Copyable conformance.
This commit is contained in:
Kavon Farvardin
2024-06-11 21:44:02 -07:00
parent 2893e3dd8d
commit a1e14ae0c7
6 changed files with 82 additions and 16 deletions

View File

@@ -801,7 +801,7 @@ public:
}
/// If there were any conditional conformances that couldn't be printed,
/// make a dummy extension that conforms to all of them, constrained by a
/// make dummy extension(s) that conforms to all of them, constrained by a
/// fake protocol.
bool printInaccessibleConformanceExtensionIfNeeded(
raw_ostream &out, const PrintOptions &printOptions,
@@ -810,20 +810,35 @@ public:
return false;
assert(nominal->isGenericContext());
if (!printOptions.printPublicInterface())
out << "@_spi(" << DummyProtocolName << ")\n";
out << "@available(*, unavailable)\nextension ";
nominal->getDeclaredType().print(out, printOptions);
out << " : ";
llvm::interleave(
ConditionalConformanceProtocols,
[&out, &printOptions](const ProtocolType *protoTy) {
protoTy->print(out, printOptions);
},
[&out] { out << ", "; });
out << " where "
<< nominal->getGenericSignature().getGenericParams().front()->getName()
<< " : " << DummyProtocolName << " {}\n";
auto emitExtension =
[&](ArrayRef<const ProtocolType *> conformanceProtos) {
if (!printOptions.printPublicInterface())
out << "@_spi(" << DummyProtocolName << ")\n";
out << "@available(*, unavailable)\nextension ";
nominal->getDeclaredType().print(out, printOptions);
out << " : ";
llvm::interleave(
conformanceProtos,
[&out, &printOptions](const ProtocolType *protoTy) {
protoTy->print(out, printOptions);
},
[&out] { out << ", "; });
out << " where "
<< nominal->getGenericSignature().getGenericParams()[0]->getName()
<< " : " << DummyProtocolName << " {}\n";
};
// We have to print conformances for invertible protocols in separate
// extensions, so do those first and save the rest for one extension.
SmallVector<const ProtocolType *, 8> regulars;
for (auto *proto : ConditionalConformanceProtocols) {
if (proto->getDecl()->getInvertibleProtocolKind()) {
emitExtension(proto);
continue;
}
regulars.push_back(proto);
}
emitExtension(regulars);
return true;
}