ModuleInterface: consider inherited protocols from super class when collecting handled protocols

Protocol conformances can be implied by super classes. When collecting the list
of IncludedProtocols, we should traverse the class inheritance chain and collect
all protocols.

Without this change, these implied conformances will be printed again via a synthesized
extension at the end of the Swift interface file, leading to an error of redundant
conformances when building modules.

rdar://58563540
This commit is contained in:
Xi Ge
2020-03-18 15:38:27 -07:00
parent a3cf3737d4
commit 45d0eca9c7
2 changed files with 32 additions and 5 deletions

View File

@@ -294,21 +294,26 @@ public:
const NominalTypeDecl *nominal;
const IterableDeclContext *memberContext;
auto shouldInclude = [](const ExtensionDecl *extension) {
if (extension->isConstrainedExtension()) {
// Conditional conformances never apply to inherited protocols, nor
// can they provide unconditional conformances that might be used in
// other extensions.
return false;
}
return true;
};
if ((nominal = dyn_cast<NominalTypeDecl>(D))) {
directlyInherited = nominal->getInherited();
memberContext = nominal;
} else if (auto *extension = dyn_cast<ExtensionDecl>(D)) {
if (extension->isConstrainedExtension()) {
// Conditional conformances never apply to inherited protocols, nor
// can they provide unconditional conformances that might be used in
// other extensions.
if (!shouldInclude(extension)) {
return;
}
nominal = extension->getExtendedNominal();
directlyInherited = extension->getInherited();
memberContext = extension;
} else {
return;
}
@@ -317,6 +322,18 @@ public:
return;
map[nominal].recordProtocols(directlyInherited, D);
// Collect protocols inherited from super classes
if (auto *CD = dyn_cast<ClassDecl>(D)) {
for (auto *SD = CD->getSuperclassDecl(); SD;
SD = SD->getSuperclassDecl()) {
map[nominal].recordProtocols(SD->getInherited(), SD);
for (auto *Ext: SD->getExtensions()) {
if (shouldInclude(Ext)) {
map[nominal].recordProtocols(Ext->getInherited(), Ext);
}
}
}
}
// Recurse to find any nested types.
for (const Decl *member : memberContext->getMembers())