[Serialization] Drop protocols whose requirements can't be loaded (#25809)

If a protocol inherits from a protocol that can't be loaded, drop it
entirely. Similarly, if it has requirements that reference types in
other modules that can't be loaded, drop the protocol entirely---at
least for now, we don't want to deal with a protocol that exists but
has the wrong requirement signature. That "in other modules" isn't
perfect, but it avoids cases where two protocols depend on each other.
Unfortunately, it means the compiler may still get into exactly the
situation above if a protocol depends on another protocol in the same
module, and /that/ protocol can't be loaded for some other reason. But
it's progress.

This comes up when referencing implementation-only-imported protocols
from non-public protocols, but is also just general deserialization
recovery goodness.

rdar://problem/52141347
This commit is contained in:
Jordan Rose
2019-06-28 20:03:37 -07:00
committed by GitHub
parent d939e786c4
commit bff83f63eb
4 changed files with 82 additions and 16 deletions

View File

@@ -3293,20 +3293,32 @@ public:
DeclContextID contextID;
bool isImplicit, isClassBounded, isObjC, existentialTypeSupported;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> rawInheritedIDs;
unsigned numInheritedTypes;
ArrayRef<uint64_t> rawInheritedAndDependencyIDs;
decls_block::ProtocolLayout::readRecord(scratch, nameID, contextID,
isImplicit, isClassBounded, isObjC,
existentialTypeSupported,
rawAccessLevel, rawInheritedIDs);
rawAccessLevel, numInheritedTypes,
rawInheritedAndDependencyIDs);
Identifier name = MF.getIdentifier(nameID);
for (TypeID dependencyID :
rawInheritedAndDependencyIDs.slice(numInheritedTypes)) {
auto dependency = MF.getTypeChecked(dependencyID);
if (!dependency) {
return llvm::make_error<TypeError>(
name, takeErrorInfo(dependency.takeError()));
}
}
auto DC = MF.getDeclContext(contextID);
if (declOrOffset.isComplete())
return declOrOffset;
auto proto = MF.createDecl<ProtocolDecl>(DC, SourceLoc(), SourceLoc(),
MF.getIdentifier(nameID), None,
/*TrailingWhere=*/nullptr);
auto proto = MF.createDecl<ProtocolDecl>(DC, SourceLoc(), SourceLoc(), name,
None, /*TrailingWhere=*/nullptr);
declOrOffset = proto;
proto->setRequiresClass(isClassBounded);
@@ -3323,7 +3335,8 @@ public:
assert(genericParams && "protocol with no generic parameters?");
proto->setGenericParams(genericParams);
handleInherited(proto, rawInheritedIDs);
handleInherited(proto,
rawInheritedAndDependencyIDs.slice(0, numInheritedTypes));
if (isImplicit)
proto->setImplicit();