[ParseableInterface] Don't print conformances from other modules (#20657)

...even if they're depended on by protocols we conform to.
This commit is contained in:
Jordan Rose
2018-11-26 17:38:24 -08:00
committed by GitHub
parent 20f29c68d9
commit 9f6de1fb8e
2 changed files with 28 additions and 2 deletions

View File

@@ -17,6 +17,7 @@
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/FileSystem.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/ParseableInterfaceSupport.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
@@ -657,12 +658,26 @@ public:
// No recursion here because extensions are never nested.
}
/// Returns true if the conformance of \p nominal to \p proto is declared in
/// module \p M.
static bool conformanceDeclaredInModule(ModuleDecl *M,
const NominalTypeDecl *nominal,
ProtocolDecl *proto) {
SmallVector<ProtocolConformance *, 4> conformances;
nominal->lookupConformance(M, proto, conformances);
return llvm::all_of(conformances,
[M](const ProtocolConformance *conformance) -> bool {
return M == conformance->getDeclContext()->getParentModule();
});
}
/// If there were any public protocols that need to be printed (i.e. they
/// weren't conformed to explicitly or inherited by another printed protocol),
/// do so now by printing a dummy extension on \p nominal to \p out.
void
printSynthesizedExtensionIfNeeded(raw_ostream &out,
const PrintOptions &printOptions,
ModuleDecl *M,
const NominalTypeDecl *nominal) const {
if (ExtraProtocols.empty())
return;
@@ -688,10 +703,13 @@ public:
[&](ProtocolDecl *inherited) -> TypeWalker::Action {
if (!handledProtocols.insert(inherited).second)
return TypeWalker::Action::SkipChildren;
if (isPublicOrUsableFromInline(inherited)) {
if (isPublicOrUsableFromInline(inherited) &&
conformanceDeclaredInModule(M, nominal, inherited)) {
protocolsToPrint.push_back(inherited);
return TypeWalker::Action::SkipChildren;
}
return TypeWalker::Action::Continue;
});
}
@@ -775,7 +793,7 @@ bool swift::emitParseableInterface(raw_ostream &out,
for (const auto &nominalAndCollector : inheritedProtocolMap) {
const NominalTypeDecl *nominal = nominalAndCollector.first;
const InheritedProtocolCollector &collector = nominalAndCollector.second;
collector.printSynthesizedExtensionIfNeeded(out, printOptions, nominal);
collector.printSynthesizedExtensionIfNeeded(out, printOptions, M, nominal);
needDummyProtocolDeclaration |=
collector.printInaccessibleConformanceExtensionIfNeeded(out,
printOptions,

View File

@@ -167,6 +167,7 @@ extension MultiGeneric: PublicProto where U: PrivateProto {}
// CHECK: public struct MultiGeneric<T, U, V> {
// CHECK-END: extension conformances.MultiGeneric : PublicProto where T : _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}
internal struct InternalImpl_BAD: PrivateSubProto {}
internal struct InternalImplConstrained_BAD<T> {}
extension InternalImplConstrained_BAD: PublicProto where T: PublicProto {}
@@ -182,5 +183,12 @@ extension WrapperForInternal.InternalImplConstrained_BAD: PublicProto where T: P
extension WrapperForInternal.InternalImplConstrained2_BAD: PublicProto where T: PrivateProto {}
internal protocol ExtraHashable: Hashable {}
extension Bool: ExtraHashable {}
// NEGATIVE-NOT: extension {{(Swift.)?}}Bool{{.+}}Hashable
// NEGATIVE-NOT: extension {{(Swift.)?}}Bool{{.+}}Equatable
// CHECK-END: @usableFromInline
// CHECK-END-NEXT: internal protocol _ConstraintThatIsNotPartOfTheAPIOfThisLibrary {}