[Serialization] Drop extensions whose base type can't be deserialized. (#11323)

This shows up with swift_wrapper typedefs, which get imported into
Swift as structs. If someone makes an extension of a swift_wrapper
type, but the swift_wrapper is only applied in Swift 4 mode, that
extension will break any Swift 3 clients. Recover by just dropping
the extension entirely.

There's still more complexity around extensions---what if a
requirement can't be deserialized? what if something's depending on
the protocol conformance provided by the extension?---but the missing
base type case should be pretty safe. If you can't see the type at
all, things that depend on its conformances are already in trouble.

rdar://problem/33636733
This commit is contained in:
Jordan Rose
2017-08-03 16:02:16 -07:00
committed by GitHub
parent d046f3f959
commit 35f8e17e88
6 changed files with 121 additions and 16 deletions

View File

@@ -1564,15 +1564,27 @@ void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
if (nominal->getParent()->isModuleScopeContext()) {
Identifier moduleName = nominal->getParentModule()->getName();
for (auto item : *iter) {
if (item.first == moduleName.str())
(void)getDecl(item.second);
if (item.first != moduleName.str())
continue;
Expected<Decl *> declOrError = getDeclChecked(item.second);
if (!declOrError) {
if (!getContext().LangOpts.EnableDeserializationRecovery)
fatal(declOrError.takeError());
llvm::consumeError(declOrError.takeError());
}
}
} else {
std::string mangledName =
Mangle::ASTMangler().mangleNominalType(nominal);
for (auto item : *iter) {
if (item.first == mangledName)
(void)getDecl(item.second);
if (item.first != mangledName)
continue;
Expected<Decl *> declOrError = getDeclChecked(item.second);
if (!declOrError) {
if (!getContext().LangOpts.EnableDeserializationRecovery)
fatal(declOrError.takeError());
llvm::consumeError(declOrError.takeError());
}
}
}
}
@@ -1751,8 +1763,16 @@ void ModuleFile::getTopLevelDecls(SmallVectorImpl<Decl *> &results) {
if (ExtensionDecls) {
for (auto entry : ExtensionDecls->data()) {
for (auto item : entry)
results.push_back(getDecl(item.second));
for (auto item : entry) {
Expected<Decl *> declOrError = getDeclChecked(item.second);
if (!declOrError) {
if (!getContext().LangOpts.EnableDeserializationRecovery)
fatal(declOrError.takeError());
llvm::consumeError(declOrError.takeError());
continue;
}
results.push_back(declOrError.get());
}
}
}
}