[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

@@ -2482,9 +2482,17 @@ void Serializer::writeDecl(const Decl *D) {
ConformanceLookupKind::All,
nullptr, /*sorted=*/true);
SmallVector<TypeID, 8> inheritedTypes;
SmallVector<TypeID, 8> inheritedAndDependencyTypes;
for (auto inherited : extension->getInherited())
inheritedTypes.push_back(addTypeRef(inherited.getType()));
inheritedAndDependencyTypes.push_back(addTypeRef(inherited.getType()));
size_t numInherited = inheritedAndDependencyTypes.size();
// FIXME: Figure out what to do with requirements and such, which the
// extension also depends on. Right now just do what is safe to drop, which
// is the base declaration.
auto dependencies = collectDependenciesFromType(baseTy);
for (auto dependencyTy : dependencies)
inheritedAndDependencyTypes.push_back(addTypeRef(dependencyTy));
unsigned abbrCode = DeclTypeAbbrCodes[ExtensionLayout::Code];
ExtensionLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -2494,7 +2502,8 @@ void Serializer::writeDecl(const Decl *D) {
addGenericEnvironmentRef(
extension->getGenericEnvironment()),
conformances.size(),
inheritedTypes);
numInherited,
inheritedAndDependencyTypes);
bool isClassExtension = false;
if (baseNominal) {