Skip to content

Commit 1168cac

Browse files
committed
[Serialization] Drop decls whose types can't be deserialized.
Proof-of-concept for the above. This shouldn't be common---renames are far more likely, and those we can track---but occurs when the swift_wrapper attribute (the implementation of NS_STRING_ENUM) is active in Swift 4 but not in Swift 3. Note that this only checks the canonical interface type of the declaration, because the non-canonical type may contain references to the declaration's generic parameters.
1 parent 10c6254 commit 1168cac

File tree

7 files changed

+158
-50
lines changed

7 files changed

+158
-50
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const unsigned char MODULE_DOC_SIGNATURE[] = { 0xE2, 0x9C, 0xA8, 0x07 };
4444

4545
/// Serialized module format major version number.
4646
///
47-
/// Always 0 for Swift 1.x - 3.x.
47+
/// Always 0 for Swift 1.x - 4.x.
4848
const uint16_t VERSION_MAJOR = 0;
4949

5050
/// Serialized module format minor version number.
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 338; // Last change: OPERAND_WITH_ATTR format.
57+
const uint16_t VERSION_MINOR = 339; // Last change: member canonical types
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -858,7 +858,8 @@ namespace decls_block {
858858
BCFixed<1>, // throws?
859859
CtorInitializerKindField, // initializer kind
860860
GenericEnvironmentIDField, // generic environment
861-
TypeIDField, // type (interface)
861+
TypeIDField, // interface type
862+
TypeIDField, // canonical interface type
862863
DeclIDField, // overridden decl
863864
AccessibilityKindField, // accessibility
864865
BCArray<IdentifierIDField> // argument names
@@ -877,6 +878,7 @@ namespace decls_block {
877878
BCFixed<1>, // HasNonPatternBindingInit?
878879
StorageKindField, // StorageKind
879880
TypeIDField, // interface type
881+
TypeIDField, // canonical interface type
880882
DeclIDField, // getter
881883
DeclIDField, // setter
882884
DeclIDField, // materializeForSet
@@ -911,6 +913,7 @@ namespace decls_block {
911913
BCVBR<5>, // number of parameter patterns
912914
GenericEnvironmentIDField, // generic environment
913915
TypeIDField, // interface type
916+
TypeIDField, // canonical interface type
914917
DeclIDField, // operator decl
915918
DeclIDField, // overridden function
916919
DeclIDField, // AccessorStorageDecl
@@ -982,6 +985,7 @@ namespace decls_block {
982985
StorageKindField, // StorageKind
983986
GenericEnvironmentIDField, // generic environment
984987
TypeIDField, // interface type
988+
TypeIDField, // canonical interface type
985989
DeclIDField, // getter
986990
DeclIDField, // setter
987991
DeclIDField, // materializeForSet

lib/Serialization/Deserialization.cpp

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@ const char XRefError::ID = '\0';
127127
void XRefError::anchor() {}
128128
const char OverrideError::ID = '\0';
129129
void OverrideError::anchor() {}
130+
const char TypeError::ID = '\0';
131+
void TypeError::anchor() {}
132+
133+
LLVM_NODISCARD
134+
static std::unique_ptr<llvm::ErrorInfoBase> takeErrorInfo(llvm::Error error) {
135+
std::unique_ptr<llvm::ErrorInfoBase> result;
136+
llvm::handleAllErrors(std::move(error),
137+
[&](std::unique_ptr<llvm::ErrorInfoBase> info) {
138+
result = std::move(info);
139+
});
140+
return result;
141+
}
130142

131143

132144
/// Skips a single record in the bitstream.
@@ -2492,7 +2504,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
24922504
bool isImplicit, isObjC, hasStubImplementation, throws;
24932505
GenericEnvironmentID genericEnvID;
24942506
uint8_t storedInitKind, rawAccessLevel;
2495-
TypeID interfaceID;
2507+
TypeID interfaceID, canonicalTypeID;
24962508
DeclID overriddenID;
24972509
ArrayRef<uint64_t> argNameIDs;
24982510

@@ -2501,8 +2513,8 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
25012513
isObjC, hasStubImplementation,
25022514
throws, storedInitKind,
25032515
genericEnvID, interfaceID,
2504-
overriddenID, rawAccessLevel,
2505-
argNameIDs);
2516+
canonicalTypeID, overriddenID,
2517+
rawAccessLevel, argNameIDs);
25062518

25072519
// Resolve the name ids.
25082520
SmallVector<Identifier, 2> argNames;
@@ -2595,15 +2607,15 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
25952607
DeclContextID contextID;
25962608
bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit;
25972609
uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
2598-
TypeID interfaceTypeID;
2610+
TypeID interfaceTypeID, canonicalTypeID;
25992611
DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
26002612
DeclID addressorID, mutableAddressorID, overriddenID;
26012613

26022614
decls_block::VarLayout::readRecord(scratch, nameID, contextID,
26032615
isImplicit, isObjC, isStatic, isLet,
26042616
hasNonPatternBindingInit, storageKind,
2605-
interfaceTypeID, getterID,
2606-
setterID, materializeForSetID,
2617+
interfaceTypeID, canonicalTypeID,
2618+
getterID, setterID, materializeForSetID,
26072619
addressorID, mutableAddressorID,
26082620
willSetID, didSetID, overriddenID,
26092621
rawAccessLevel, rawSetterAccessLevel);
@@ -2616,6 +2628,10 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
26162628
return llvm::make_error<OverrideError>(name);
26172629
}
26182630

2631+
auto canonicalType = getTypeChecked(canonicalTypeID);
2632+
if (!canonicalType)
2633+
return llvm::make_error<TypeError>(name, takeErrorInfo(canonicalType.takeError()));
2634+
26192635
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
26202636
if (declOrOffset.isComplete())
26212637
return declOrOffset;
@@ -2703,7 +2719,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
27032719
bool isObjC, isMutating, hasDynamicSelf, throws;
27042720
unsigned numParamPatterns;
27052721
GenericEnvironmentID genericEnvID;
2706-
TypeID interfaceTypeID;
2722+
TypeID interfaceTypeID, canonicalTypeID;
27072723
DeclID associatedDeclID;
27082724
DeclID overriddenID;
27092725
DeclID accessorStorageDeclID;
@@ -2714,10 +2730,11 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
27142730
isStatic, rawStaticSpelling, isObjC,
27152731
isMutating, hasDynamicSelf, throws,
27162732
numParamPatterns, genericEnvID,
2717-
interfaceTypeID, associatedDeclID,
2718-
overriddenID, accessorStorageDeclID,
2719-
hasCompoundName, rawAddressorKind,
2720-
rawAccessLevel, nameIDs);
2733+
interfaceTypeID, canonicalTypeID,
2734+
associatedDeclID, overriddenID,
2735+
accessorStorageDeclID, hasCompoundName,
2736+
rawAddressorKind, rawAccessLevel,
2737+
nameIDs);
27212738

27222739
// Resolve the name ids.
27232740
SmallVector<Identifier, 2> names;
@@ -3237,7 +3254,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
32373254
DeclContextID contextID;
32383255
bool isImplicit, isObjC;
32393256
GenericEnvironmentID genericEnvID;
3240-
TypeID interfaceTypeID;
3257+
TypeID interfaceTypeID, canonicalTypeID;
32413258
DeclID getterID, setterID, materializeForSetID;
32423259
DeclID addressorID, mutableAddressorID, willSetID, didSetID;
32433260
DeclID overriddenID;
@@ -3248,7 +3265,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
32483265
decls_block::SubscriptLayout::readRecord(scratch, contextID,
32493266
isImplicit, isObjC, rawStorageKind,
32503267
genericEnvID,
3251-
interfaceTypeID,
3268+
interfaceTypeID, canonicalTypeID,
32523269
getterID, setterID,
32533270
materializeForSetID,
32543271
addressorID, mutableAddressorID,
@@ -3587,17 +3604,20 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
35873604
TypeID canonicalTypeID;
35883605
decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID,
35893606
canonicalTypeID);
3590-
auto alias = dyn_cast_or_null<TypeAliasDecl>(getDecl(underlyingID));
3591-
if (!alias) {
3592-
error();
3593-
return nullptr;
3594-
}
3607+
auto aliasOrError = getDeclChecked(underlyingID);
3608+
if (!aliasOrError)
3609+
return aliasOrError.takeError();
3610+
auto alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());
35953611

35963612
if (ctx.LangOpts.EnableDeserializationRecovery) {
3597-
if (Type expectedType = getType(canonicalTypeID)) {
3598-
if (!alias->getDeclaredInterfaceType()->isEqual(expectedType)) {
3613+
Expected<Type> expectedType = getTypeChecked(canonicalTypeID);
3614+
if (!expectedType)
3615+
return expectedType.takeError();
3616+
if (expectedType.get()) {
3617+
if (!alias ||
3618+
!alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) {
35993619
// Fall back to the canonical type.
3600-
typeOrOffset = expectedType;
3620+
typeOrOffset = expectedType.get();
36013621
break;
36023622
}
36033623
}
@@ -3619,12 +3639,22 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
36193639
TypeID parentID;
36203640
decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);
36213641

3622-
Type parentTy = getType(parentID);
3642+
Expected<Type> parentTy = getTypeChecked(parentID);
3643+
if (!parentTy)
3644+
return parentTy.takeError();
36233645

3624-
// Record the type as soon as possible. Members of a nominal type often
3625-
// try to refer back to the type.
3626-
auto nominal = cast<NominalTypeDecl>(getDecl(declID));
3627-
typeOrOffset = NominalType::get(nominal, parentTy, ctx);
3646+
auto nominalOrError = getDeclChecked(declID);
3647+
if (!nominalOrError)
3648+
return nominalOrError.takeError();
3649+
3650+
auto nominal = dyn_cast<NominalTypeDecl>(nominalOrError.get());
3651+
if (!nominal) {
3652+
XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()};
3653+
tinyTrace.addValue(cast<ValueDecl>(nominalOrError.get())->getName());
3654+
return llvm::make_error<XRefError>("declaration is not a nominal type",
3655+
tinyTrace);
3656+
}
3657+
typeOrOffset = NominalType::get(nominal, parentTy.get(), ctx);
36283658

36293659
assert(typeOrOffset.isComplete());
36303660
break;

lib/Serialization/DeserializationErrors.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,30 @@ class OverrideError : public llvm::ErrorInfo<OverrideError,
248248
}
249249
};
250250

251+
class TypeError : public llvm::ErrorInfo<TypeError, DeclDeserializationError> {
252+
friend ErrorInfo;
253+
static const char ID;
254+
void anchor() override;
255+
256+
DeclName name;
257+
std::unique_ptr<ErrorInfoBase> underlyingReason;
258+
public:
259+
explicit TypeError(DeclName name, std::unique_ptr<ErrorInfoBase> reason)
260+
: name(name), underlyingReason(std::move(reason)) {}
261+
262+
void log(raw_ostream &OS) const override {
263+
OS << "could not deserialize type for '" << name << "'";
264+
if (underlyingReason) {
265+
OS << ": ";
266+
underlyingReason->log(OS);
267+
}
268+
}
269+
270+
std::error_code convertToErrorCode() const override {
271+
return llvm::inconvertibleErrorCode();
272+
}
273+
};
274+
251275
} // end namespace serialization
252276
} // end namespace swift
253277

lib/Serialization/ModuleFile.cpp

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Serialization/ModuleFile.h"
14+
#include "DeserializationErrors.h"
1415
#include "swift/Serialization/ModuleFormat.h"
1516
#include "swift/Subsystems.h"
1617
#include "swift/AST/ASTContext.h"
@@ -31,6 +32,7 @@
3132
using namespace swift;
3233
using namespace swift::serialization;
3334
using namespace llvm::support;
35+
using llvm::Expected;
3436

3537
static bool checkModuleSignature(llvm::BitstreamCursor &cursor) {
3638
for (unsigned char byte : MODULE_SIGNATURE)
@@ -1310,17 +1312,17 @@ void ModuleFile::lookupValue(DeclName name,
13101312
// serialized.
13111313
auto iter = TopLevelDecls->find(name.getBaseName());
13121314
if (iter != TopLevelDecls->end()) {
1313-
if (name.isSimpleName()) {
1314-
for (auto item : *iter) {
1315-
auto VD = cast<ValueDecl>(getDecl(item.second));
1316-
results.push_back(VD);
1317-
}
1318-
} else {
1319-
for (auto item : *iter) {
1320-
auto VD = cast<ValueDecl>(getDecl(item.second));
1321-
if (VD->getFullName().matchesRef(name))
1322-
results.push_back(VD);
1315+
for (auto item : *iter) {
1316+
Expected<Decl *> declOrError = getDeclChecked(item.second);
1317+
if (!declOrError) {
1318+
if (!getContext().LangOpts.EnableDeserializationRecovery)
1319+
fatal(declOrError.takeError());
1320+
llvm::consumeError(declOrError.takeError());
1321+
continue;
13231322
}
1323+
auto VD = cast<ValueDecl>(declOrError.get());
1324+
if (name.isSimpleName() || VD->getFullName().matchesRef(name))
1325+
results.push_back(VD);
13241326
}
13251327
}
13261328
}
@@ -1503,21 +1505,32 @@ void ModuleFile::lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
15031505
if (!TopLevelDecls)
15041506
return;
15051507

1508+
auto tryImport = [this, &consumer](DeclID ID) {
1509+
Expected<Decl *> declOrError = getDeclChecked(ID);
1510+
if (!declOrError) {
1511+
if (!getContext().LangOpts.EnableDeserializationRecovery)
1512+
fatal(declOrError.takeError());
1513+
llvm::consumeError(declOrError.takeError());
1514+
return;
1515+
}
1516+
consumer.foundDecl(cast<ValueDecl>(declOrError.get()),
1517+
DeclVisibilityKind::VisibleAtTopLevel);
1518+
};
1519+
15061520
if (!accessPath.empty()) {
15071521
auto iter = TopLevelDecls->find(accessPath.front().first);
15081522
if (iter == TopLevelDecls->end())
15091523
return;
15101524

15111525
for (auto item : *iter)
1512-
consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
1513-
DeclVisibilityKind::VisibleAtTopLevel);
1526+
tryImport(item.second);
1527+
15141528
return;
15151529
}
15161530

15171531
for (auto entry : TopLevelDecls->data()) {
15181532
for (auto item : entry)
1519-
consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
1520-
DeclVisibilityKind::VisibleAtTopLevel);
1533+
tryImport(item.second);
15211534
}
15221535
}
15231536

@@ -1711,8 +1724,16 @@ void ModuleFile::getTopLevelDecls(SmallVectorImpl<Decl *> &results) {
17111724

17121725
if (TopLevelDecls) {
17131726
for (auto entry : TopLevelDecls->data()) {
1714-
for (auto item : entry)
1715-
results.push_back(getDecl(item.second));
1727+
for (auto item : entry) {
1728+
Expected<Decl *> declOrError = getDeclChecked(item.second);
1729+
if (!declOrError) {
1730+
if (!getContext().LangOpts.EnableDeserializationRecovery)
1731+
fatal(declOrError.takeError());
1732+
llvm::consumeError(declOrError.takeError());
1733+
continue;
1734+
}
1735+
results.push_back(declOrError.get());
1736+
}
17161737
}
17171738
}
17181739

0 commit comments

Comments
 (0)