mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -44,7 +44,7 @@ const unsigned char MODULE_DOC_SIGNATURE[] = { 0xE2, 0x9C, 0xA8, 0x07 };
|
|||||||
|
|
||||||
/// Serialized module format major version number.
|
/// Serialized module format major version number.
|
||||||
///
|
///
|
||||||
/// Always 0 for Swift 1.x - 3.x.
|
/// Always 0 for Swift 1.x - 4.x.
|
||||||
const uint16_t VERSION_MAJOR = 0;
|
const uint16_t VERSION_MAJOR = 0;
|
||||||
|
|
||||||
/// Serialized module format minor version number.
|
/// Serialized module format minor version number.
|
||||||
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
|
|||||||
/// in source control, you should also update the comment to briefly
|
/// in source control, you should also update the comment to briefly
|
||||||
/// describe what change you made. The content of this comment isn't important;
|
/// describe what change you made. The content of this comment isn't important;
|
||||||
/// it just ensures a conflict if two people change the module format.
|
/// it just ensures a conflict if two people change the module format.
|
||||||
const uint16_t VERSION_MINOR = 338; // Last change: OPERAND_WITH_ATTR format.
|
const uint16_t VERSION_MINOR = 339; // Last change: member canonical types
|
||||||
|
|
||||||
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
using DeclID = PointerEmbeddedInt<unsigned, 31>;
|
||||||
using DeclIDField = BCFixed<31>;
|
using DeclIDField = BCFixed<31>;
|
||||||
@@ -858,7 +858,8 @@ namespace decls_block {
|
|||||||
BCFixed<1>, // throws?
|
BCFixed<1>, // throws?
|
||||||
CtorInitializerKindField, // initializer kind
|
CtorInitializerKindField, // initializer kind
|
||||||
GenericEnvironmentIDField, // generic environment
|
GenericEnvironmentIDField, // generic environment
|
||||||
TypeIDField, // type (interface)
|
TypeIDField, // interface type
|
||||||
|
TypeIDField, // canonical interface type
|
||||||
DeclIDField, // overridden decl
|
DeclIDField, // overridden decl
|
||||||
AccessibilityKindField, // accessibility
|
AccessibilityKindField, // accessibility
|
||||||
BCArray<IdentifierIDField> // argument names
|
BCArray<IdentifierIDField> // argument names
|
||||||
@@ -877,6 +878,7 @@ namespace decls_block {
|
|||||||
BCFixed<1>, // HasNonPatternBindingInit?
|
BCFixed<1>, // HasNonPatternBindingInit?
|
||||||
StorageKindField, // StorageKind
|
StorageKindField, // StorageKind
|
||||||
TypeIDField, // interface type
|
TypeIDField, // interface type
|
||||||
|
TypeIDField, // canonical interface type
|
||||||
DeclIDField, // getter
|
DeclIDField, // getter
|
||||||
DeclIDField, // setter
|
DeclIDField, // setter
|
||||||
DeclIDField, // materializeForSet
|
DeclIDField, // materializeForSet
|
||||||
@@ -911,6 +913,7 @@ namespace decls_block {
|
|||||||
BCVBR<5>, // number of parameter patterns
|
BCVBR<5>, // number of parameter patterns
|
||||||
GenericEnvironmentIDField, // generic environment
|
GenericEnvironmentIDField, // generic environment
|
||||||
TypeIDField, // interface type
|
TypeIDField, // interface type
|
||||||
|
TypeIDField, // canonical interface type
|
||||||
DeclIDField, // operator decl
|
DeclIDField, // operator decl
|
||||||
DeclIDField, // overridden function
|
DeclIDField, // overridden function
|
||||||
DeclIDField, // AccessorStorageDecl
|
DeclIDField, // AccessorStorageDecl
|
||||||
@@ -982,6 +985,7 @@ namespace decls_block {
|
|||||||
StorageKindField, // StorageKind
|
StorageKindField, // StorageKind
|
||||||
GenericEnvironmentIDField, // generic environment
|
GenericEnvironmentIDField, // generic environment
|
||||||
TypeIDField, // interface type
|
TypeIDField, // interface type
|
||||||
|
TypeIDField, // canonical interface type
|
||||||
DeclIDField, // getter
|
DeclIDField, // getter
|
||||||
DeclIDField, // setter
|
DeclIDField, // setter
|
||||||
DeclIDField, // materializeForSet
|
DeclIDField, // materializeForSet
|
||||||
|
|||||||
@@ -127,6 +127,18 @@ const char XRefError::ID = '\0';
|
|||||||
void XRefError::anchor() {}
|
void XRefError::anchor() {}
|
||||||
const char OverrideError::ID = '\0';
|
const char OverrideError::ID = '\0';
|
||||||
void OverrideError::anchor() {}
|
void OverrideError::anchor() {}
|
||||||
|
const char TypeError::ID = '\0';
|
||||||
|
void TypeError::anchor() {}
|
||||||
|
|
||||||
|
LLVM_NODISCARD
|
||||||
|
static std::unique_ptr<llvm::ErrorInfoBase> takeErrorInfo(llvm::Error error) {
|
||||||
|
std::unique_ptr<llvm::ErrorInfoBase> result;
|
||||||
|
llvm::handleAllErrors(std::move(error),
|
||||||
|
[&](std::unique_ptr<llvm::ErrorInfoBase> info) {
|
||||||
|
result = std::move(info);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Skips a single record in the bitstream.
|
/// Skips a single record in the bitstream.
|
||||||
@@ -2492,7 +2504,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
bool isImplicit, isObjC, hasStubImplementation, throws;
|
bool isImplicit, isObjC, hasStubImplementation, throws;
|
||||||
GenericEnvironmentID genericEnvID;
|
GenericEnvironmentID genericEnvID;
|
||||||
uint8_t storedInitKind, rawAccessLevel;
|
uint8_t storedInitKind, rawAccessLevel;
|
||||||
TypeID interfaceID;
|
TypeID interfaceID, canonicalTypeID;
|
||||||
DeclID overriddenID;
|
DeclID overriddenID;
|
||||||
ArrayRef<uint64_t> argNameIDs;
|
ArrayRef<uint64_t> argNameIDs;
|
||||||
|
|
||||||
@@ -2501,8 +2513,8 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
isObjC, hasStubImplementation,
|
isObjC, hasStubImplementation,
|
||||||
throws, storedInitKind,
|
throws, storedInitKind,
|
||||||
genericEnvID, interfaceID,
|
genericEnvID, interfaceID,
|
||||||
overriddenID, rawAccessLevel,
|
canonicalTypeID, overriddenID,
|
||||||
argNameIDs);
|
rawAccessLevel, argNameIDs);
|
||||||
|
|
||||||
// Resolve the name ids.
|
// Resolve the name ids.
|
||||||
SmallVector<Identifier, 2> argNames;
|
SmallVector<Identifier, 2> argNames;
|
||||||
@@ -2595,15 +2607,15 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
DeclContextID contextID;
|
DeclContextID contextID;
|
||||||
bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit;
|
bool isImplicit, isObjC, isStatic, isLet, hasNonPatternBindingInit;
|
||||||
uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
|
uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
|
||||||
TypeID interfaceTypeID;
|
TypeID interfaceTypeID, canonicalTypeID;
|
||||||
DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
|
DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
|
||||||
DeclID addressorID, mutableAddressorID, overriddenID;
|
DeclID addressorID, mutableAddressorID, overriddenID;
|
||||||
|
|
||||||
decls_block::VarLayout::readRecord(scratch, nameID, contextID,
|
decls_block::VarLayout::readRecord(scratch, nameID, contextID,
|
||||||
isImplicit, isObjC, isStatic, isLet,
|
isImplicit, isObjC, isStatic, isLet,
|
||||||
hasNonPatternBindingInit, storageKind,
|
hasNonPatternBindingInit, storageKind,
|
||||||
interfaceTypeID, getterID,
|
interfaceTypeID, canonicalTypeID,
|
||||||
setterID, materializeForSetID,
|
getterID, setterID, materializeForSetID,
|
||||||
addressorID, mutableAddressorID,
|
addressorID, mutableAddressorID,
|
||||||
willSetID, didSetID, overriddenID,
|
willSetID, didSetID, overriddenID,
|
||||||
rawAccessLevel, rawSetterAccessLevel);
|
rawAccessLevel, rawSetterAccessLevel);
|
||||||
@@ -2616,6 +2628,10 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
return llvm::make_error<OverrideError>(name);
|
return llvm::make_error<OverrideError>(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto canonicalType = getTypeChecked(canonicalTypeID);
|
||||||
|
if (!canonicalType)
|
||||||
|
return llvm::make_error<TypeError>(name, takeErrorInfo(canonicalType.takeError()));
|
||||||
|
|
||||||
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
|
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
|
||||||
if (declOrOffset.isComplete())
|
if (declOrOffset.isComplete())
|
||||||
return declOrOffset;
|
return declOrOffset;
|
||||||
@@ -2703,7 +2719,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
bool isObjC, isMutating, hasDynamicSelf, throws;
|
bool isObjC, isMutating, hasDynamicSelf, throws;
|
||||||
unsigned numParamPatterns;
|
unsigned numParamPatterns;
|
||||||
GenericEnvironmentID genericEnvID;
|
GenericEnvironmentID genericEnvID;
|
||||||
TypeID interfaceTypeID;
|
TypeID interfaceTypeID, canonicalTypeID;
|
||||||
DeclID associatedDeclID;
|
DeclID associatedDeclID;
|
||||||
DeclID overriddenID;
|
DeclID overriddenID;
|
||||||
DeclID accessorStorageDeclID;
|
DeclID accessorStorageDeclID;
|
||||||
@@ -2714,10 +2730,11 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
isStatic, rawStaticSpelling, isObjC,
|
isStatic, rawStaticSpelling, isObjC,
|
||||||
isMutating, hasDynamicSelf, throws,
|
isMutating, hasDynamicSelf, throws,
|
||||||
numParamPatterns, genericEnvID,
|
numParamPatterns, genericEnvID,
|
||||||
interfaceTypeID, associatedDeclID,
|
interfaceTypeID, canonicalTypeID,
|
||||||
overriddenID, accessorStorageDeclID,
|
associatedDeclID, overriddenID,
|
||||||
hasCompoundName, rawAddressorKind,
|
accessorStorageDeclID, hasCompoundName,
|
||||||
rawAccessLevel, nameIDs);
|
rawAddressorKind, rawAccessLevel,
|
||||||
|
nameIDs);
|
||||||
|
|
||||||
// Resolve the name ids.
|
// Resolve the name ids.
|
||||||
SmallVector<Identifier, 2> names;
|
SmallVector<Identifier, 2> names;
|
||||||
@@ -3237,7 +3254,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
DeclContextID contextID;
|
DeclContextID contextID;
|
||||||
bool isImplicit, isObjC;
|
bool isImplicit, isObjC;
|
||||||
GenericEnvironmentID genericEnvID;
|
GenericEnvironmentID genericEnvID;
|
||||||
TypeID interfaceTypeID;
|
TypeID interfaceTypeID, canonicalTypeID;
|
||||||
DeclID getterID, setterID, materializeForSetID;
|
DeclID getterID, setterID, materializeForSetID;
|
||||||
DeclID addressorID, mutableAddressorID, willSetID, didSetID;
|
DeclID addressorID, mutableAddressorID, willSetID, didSetID;
|
||||||
DeclID overriddenID;
|
DeclID overriddenID;
|
||||||
@@ -3248,7 +3265,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
|||||||
decls_block::SubscriptLayout::readRecord(scratch, contextID,
|
decls_block::SubscriptLayout::readRecord(scratch, contextID,
|
||||||
isImplicit, isObjC, rawStorageKind,
|
isImplicit, isObjC, rawStorageKind,
|
||||||
genericEnvID,
|
genericEnvID,
|
||||||
interfaceTypeID,
|
interfaceTypeID, canonicalTypeID,
|
||||||
getterID, setterID,
|
getterID, setterID,
|
||||||
materializeForSetID,
|
materializeForSetID,
|
||||||
addressorID, mutableAddressorID,
|
addressorID, mutableAddressorID,
|
||||||
@@ -3587,17 +3604,20 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
|
|||||||
TypeID canonicalTypeID;
|
TypeID canonicalTypeID;
|
||||||
decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID,
|
decls_block::NameAliasTypeLayout::readRecord(scratch, underlyingID,
|
||||||
canonicalTypeID);
|
canonicalTypeID);
|
||||||
auto alias = dyn_cast_or_null<TypeAliasDecl>(getDecl(underlyingID));
|
auto aliasOrError = getDeclChecked(underlyingID);
|
||||||
if (!alias) {
|
if (!aliasOrError)
|
||||||
error();
|
return aliasOrError.takeError();
|
||||||
return nullptr;
|
auto alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.LangOpts.EnableDeserializationRecovery) {
|
if (ctx.LangOpts.EnableDeserializationRecovery) {
|
||||||
if (Type expectedType = getType(canonicalTypeID)) {
|
Expected<Type> expectedType = getTypeChecked(canonicalTypeID);
|
||||||
if (!alias->getDeclaredInterfaceType()->isEqual(expectedType)) {
|
if (!expectedType)
|
||||||
|
return expectedType.takeError();
|
||||||
|
if (expectedType.get()) {
|
||||||
|
if (!alias ||
|
||||||
|
!alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) {
|
||||||
// Fall back to the canonical type.
|
// Fall back to the canonical type.
|
||||||
typeOrOffset = expectedType;
|
typeOrOffset = expectedType.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3619,12 +3639,22 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
|
|||||||
TypeID parentID;
|
TypeID parentID;
|
||||||
decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);
|
decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);
|
||||||
|
|
||||||
Type parentTy = getType(parentID);
|
Expected<Type> parentTy = getTypeChecked(parentID);
|
||||||
|
if (!parentTy)
|
||||||
|
return parentTy.takeError();
|
||||||
|
|
||||||
// Record the type as soon as possible. Members of a nominal type often
|
auto nominalOrError = getDeclChecked(declID);
|
||||||
// try to refer back to the type.
|
if (!nominalOrError)
|
||||||
auto nominal = cast<NominalTypeDecl>(getDecl(declID));
|
return nominalOrError.takeError();
|
||||||
typeOrOffset = NominalType::get(nominal, parentTy, ctx);
|
|
||||||
|
auto nominal = dyn_cast<NominalTypeDecl>(nominalOrError.get());
|
||||||
|
if (!nominal) {
|
||||||
|
XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()};
|
||||||
|
tinyTrace.addValue(cast<ValueDecl>(nominalOrError.get())->getName());
|
||||||
|
return llvm::make_error<XRefError>("declaration is not a nominal type",
|
||||||
|
tinyTrace);
|
||||||
|
}
|
||||||
|
typeOrOffset = NominalType::get(nominal, parentTy.get(), ctx);
|
||||||
|
|
||||||
assert(typeOrOffset.isComplete());
|
assert(typeOrOffset.isComplete());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -248,6 +248,30 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TypeError : public llvm::ErrorInfo<TypeError, DeclDeserializationError> {
|
||||||
|
friend ErrorInfo;
|
||||||
|
static const char ID;
|
||||||
|
void anchor() override;
|
||||||
|
|
||||||
|
DeclName name;
|
||||||
|
std::unique_ptr<ErrorInfoBase> underlyingReason;
|
||||||
|
public:
|
||||||
|
explicit TypeError(DeclName name, std::unique_ptr<ErrorInfoBase> reason)
|
||||||
|
: name(name), underlyingReason(std::move(reason)) {}
|
||||||
|
|
||||||
|
void log(raw_ostream &OS) const override {
|
||||||
|
OS << "could not deserialize type for '" << name << "'";
|
||||||
|
if (underlyingReason) {
|
||||||
|
OS << ": ";
|
||||||
|
underlyingReason->log(OS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code convertToErrorCode() const override {
|
||||||
|
return llvm::inconvertibleErrorCode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace serialization
|
} // end namespace serialization
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "swift/Serialization/ModuleFile.h"
|
#include "swift/Serialization/ModuleFile.h"
|
||||||
|
#include "DeserializationErrors.h"
|
||||||
#include "swift/Serialization/ModuleFormat.h"
|
#include "swift/Serialization/ModuleFormat.h"
|
||||||
#include "swift/Subsystems.h"
|
#include "swift/Subsystems.h"
|
||||||
#include "swift/AST/ASTContext.h"
|
#include "swift/AST/ASTContext.h"
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
using namespace swift;
|
using namespace swift;
|
||||||
using namespace swift::serialization;
|
using namespace swift::serialization;
|
||||||
using namespace llvm::support;
|
using namespace llvm::support;
|
||||||
|
using llvm::Expected;
|
||||||
|
|
||||||
static bool checkModuleSignature(llvm::BitstreamCursor &cursor) {
|
static bool checkModuleSignature(llvm::BitstreamCursor &cursor) {
|
||||||
for (unsigned char byte : MODULE_SIGNATURE)
|
for (unsigned char byte : MODULE_SIGNATURE)
|
||||||
@@ -1310,20 +1312,20 @@ void ModuleFile::lookupValue(DeclName name,
|
|||||||
// serialized.
|
// serialized.
|
||||||
auto iter = TopLevelDecls->find(name.getBaseName());
|
auto iter = TopLevelDecls->find(name.getBaseName());
|
||||||
if (iter != TopLevelDecls->end()) {
|
if (iter != TopLevelDecls->end()) {
|
||||||
if (name.isSimpleName()) {
|
|
||||||
for (auto item : *iter) {
|
for (auto item : *iter) {
|
||||||
auto VD = cast<ValueDecl>(getDecl(item.second));
|
Expected<Decl *> declOrError = getDeclChecked(item.second);
|
||||||
results.push_back(VD);
|
if (!declOrError) {
|
||||||
|
if (!getContext().LangOpts.EnableDeserializationRecovery)
|
||||||
|
fatal(declOrError.takeError());
|
||||||
|
llvm::consumeError(declOrError.takeError());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
auto VD = cast<ValueDecl>(declOrError.get());
|
||||||
for (auto item : *iter) {
|
if (name.isSimpleName() || VD->getFullName().matchesRef(name))
|
||||||
auto VD = cast<ValueDecl>(getDecl(item.second));
|
|
||||||
if (VD->getFullName().matchesRef(name))
|
|
||||||
results.push_back(VD);
|
results.push_back(VD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the name is an operator name, also look for operator methods.
|
// If the name is an operator name, also look for operator methods.
|
||||||
if (name.isOperator() && OperatorMethodDecls) {
|
if (name.isOperator() && OperatorMethodDecls) {
|
||||||
@@ -1503,21 +1505,32 @@ void ModuleFile::lookupVisibleDecls(ModuleDecl::AccessPathTy accessPath,
|
|||||||
if (!TopLevelDecls)
|
if (!TopLevelDecls)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto tryImport = [this, &consumer](DeclID ID) {
|
||||||
|
Expected<Decl *> declOrError = getDeclChecked(ID);
|
||||||
|
if (!declOrError) {
|
||||||
|
if (!getContext().LangOpts.EnableDeserializationRecovery)
|
||||||
|
fatal(declOrError.takeError());
|
||||||
|
llvm::consumeError(declOrError.takeError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
consumer.foundDecl(cast<ValueDecl>(declOrError.get()),
|
||||||
|
DeclVisibilityKind::VisibleAtTopLevel);
|
||||||
|
};
|
||||||
|
|
||||||
if (!accessPath.empty()) {
|
if (!accessPath.empty()) {
|
||||||
auto iter = TopLevelDecls->find(accessPath.front().first);
|
auto iter = TopLevelDecls->find(accessPath.front().first);
|
||||||
if (iter == TopLevelDecls->end())
|
if (iter == TopLevelDecls->end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto item : *iter)
|
for (auto item : *iter)
|
||||||
consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
|
tryImport(item.second);
|
||||||
DeclVisibilityKind::VisibleAtTopLevel);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto entry : TopLevelDecls->data()) {
|
for (auto entry : TopLevelDecls->data()) {
|
||||||
for (auto item : entry)
|
for (auto item : entry)
|
||||||
consumer.foundDecl(cast<ValueDecl>(getDecl(item.second)),
|
tryImport(item.second);
|
||||||
DeclVisibilityKind::VisibleAtTopLevel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1711,8 +1724,16 @@ void ModuleFile::getTopLevelDecls(SmallVectorImpl<Decl *> &results) {
|
|||||||
|
|
||||||
if (TopLevelDecls) {
|
if (TopLevelDecls) {
|
||||||
for (auto entry : TopLevelDecls->data()) {
|
for (auto entry : TopLevelDecls->data()) {
|
||||||
for (auto item : entry)
|
for (auto item : entry) {
|
||||||
results.push_back(getDecl(item.second));
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2761,6 +2761,7 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
if (var->isSettable(nullptr))
|
if (var->isSettable(nullptr))
|
||||||
rawSetterAccessLevel =
|
rawSetterAccessLevel =
|
||||||
getRawStableAccessibility(var->getSetterAccessibility());
|
getRawStableAccessibility(var->getSetterAccessibility());
|
||||||
|
Type ty = var->getInterfaceType();
|
||||||
|
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[VarLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[VarLayout::Code];
|
||||||
VarLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
VarLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
@@ -2772,7 +2773,8 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
var->isLet(),
|
var->isLet(),
|
||||||
var->hasNonPatternBindingInit(),
|
var->hasNonPatternBindingInit(),
|
||||||
(unsigned) accessors.Kind,
|
(unsigned) accessors.Kind,
|
||||||
addTypeRef(var->getInterfaceType()),
|
addTypeRef(ty),
|
||||||
|
addTypeRef(ty->getCanonicalType()),
|
||||||
addDeclRef(accessors.Get),
|
addDeclRef(accessors.Get),
|
||||||
addDeclRef(accessors.Set),
|
addDeclRef(accessors.Set),
|
||||||
addDeclRef(accessors.MaterializeForSet),
|
addDeclRef(accessors.MaterializeForSet),
|
||||||
@@ -2824,6 +2826,7 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
getRawStableAccessibility(fn->getFormalAccess());
|
getRawStableAccessibility(fn->getFormalAccess());
|
||||||
uint8_t rawAddressorKind =
|
uint8_t rawAddressorKind =
|
||||||
getRawStableAddressorKind(fn->getAddressorKind());
|
getRawStableAddressorKind(fn->getAddressorKind());
|
||||||
|
Type ty = fn->getInterfaceType();
|
||||||
|
|
||||||
FuncLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
FuncLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
contextID,
|
contextID,
|
||||||
@@ -2838,7 +2841,8 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
fn->getParameterLists().size(),
|
fn->getParameterLists().size(),
|
||||||
addGenericEnvironmentRef(
|
addGenericEnvironmentRef(
|
||||||
fn->getGenericEnvironment()),
|
fn->getGenericEnvironment()),
|
||||||
addTypeRef(fn->getInterfaceType()),
|
addTypeRef(ty),
|
||||||
|
addTypeRef(ty->getCanonicalType()),
|
||||||
addDeclRef(fn->getOperatorDecl()),
|
addDeclRef(fn->getOperatorDecl()),
|
||||||
addDeclRef(fn->getOverriddenDecl()),
|
addDeclRef(fn->getOverriddenDecl()),
|
||||||
addDeclRef(fn->getAccessorStorageDecl()),
|
addDeclRef(fn->getAccessorStorageDecl()),
|
||||||
@@ -2906,6 +2910,7 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
if (subscript->isSettable())
|
if (subscript->isSettable())
|
||||||
rawSetterAccessLevel =
|
rawSetterAccessLevel =
|
||||||
getRawStableAccessibility(subscript->getSetterAccessibility());
|
getRawStableAccessibility(subscript->getSetterAccessibility());
|
||||||
|
Type ty = subscript->getInterfaceType();
|
||||||
|
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[SubscriptLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[SubscriptLayout::Code];
|
||||||
SubscriptLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
SubscriptLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
@@ -2915,7 +2920,8 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
(unsigned) accessors.Kind,
|
(unsigned) accessors.Kind,
|
||||||
addGenericEnvironmentRef(
|
addGenericEnvironmentRef(
|
||||||
subscript->getGenericEnvironment()),
|
subscript->getGenericEnvironment()),
|
||||||
addTypeRef(subscript->getInterfaceType()),
|
addTypeRef(ty),
|
||||||
|
addTypeRef(ty->getCanonicalType()),
|
||||||
addDeclRef(accessors.Get),
|
addDeclRef(accessors.Get),
|
||||||
addDeclRef(accessors.Set),
|
addDeclRef(accessors.Set),
|
||||||
addDeclRef(accessors.MaterializeForSet),
|
addDeclRef(accessors.MaterializeForSet),
|
||||||
@@ -2946,6 +2952,7 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
|
|
||||||
uint8_t rawAccessLevel =
|
uint8_t rawAccessLevel =
|
||||||
getRawStableAccessibility(ctor->getFormalAccess());
|
getRawStableAccessibility(ctor->getFormalAccess());
|
||||||
|
Type ty = ctor->getInterfaceType();
|
||||||
|
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[ConstructorLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[ConstructorLayout::Code];
|
||||||
ConstructorLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
ConstructorLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||||
@@ -2960,7 +2967,8 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
ctor->getInitKind()),
|
ctor->getInitKind()),
|
||||||
addGenericEnvironmentRef(
|
addGenericEnvironmentRef(
|
||||||
ctor->getGenericEnvironment()),
|
ctor->getGenericEnvironment()),
|
||||||
addTypeRef(ctor->getInterfaceType()),
|
addTypeRef(ty),
|
||||||
|
addTypeRef(ty->getCanonicalType()),
|
||||||
addDeclRef(ctor->getOverriddenDecl()),
|
addDeclRef(ctor->getOverriddenDecl()),
|
||||||
rawAccessLevel,
|
rawAccessLevel,
|
||||||
nameComponents);
|
nameComponents);
|
||||||
|
|||||||
@@ -9,3 +9,11 @@ struct ImportedType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef MysteryTypedef ImportedTypeAssoc __attribute__((swift_name("ImportedType.Assoc")));
|
typedef MysteryTypedef ImportedTypeAssoc __attribute__((swift_name("ImportedType.Assoc")));
|
||||||
|
|
||||||
|
#if !BAD
|
||||||
|
typedef int WrappedInt __attribute__((swift_wrapper(struct)));
|
||||||
|
typedef int UnwrappedInt;
|
||||||
|
#else
|
||||||
|
typedef int WrappedInt;
|
||||||
|
typedef int UnwrappedInt __attribute__((swift_wrapper(struct)));
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
|
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
|
||||||
|
|
||||||
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -enable-experimental-deserialization-recovery | %FileCheck -check-prefix CHECK-RECOVERY %s
|
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -enable-experimental-deserialization-recovery > %t.txt
|
||||||
|
// RUN: %FileCheck -check-prefix CHECK-RECOVERY %s < %t.txt
|
||||||
|
// RUN: %FileCheck -check-prefix CHECK-RECOVERY-NEGATIVE %s < %t.txt
|
||||||
|
|
||||||
// RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery -DVERIFY %s -verify
|
// RUN: %target-swift-frontend -typecheck -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery -DVERIFY %s -verify
|
||||||
// RUN: %target-swift-frontend -emit-silgen -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery %s | %FileCheck -check-prefix CHECK-SIL %s
|
// RUN: %target-swift-frontend -emit-silgen -I %t -I %S/Inputs/custom-modules -Xcc -DBAD -DTEST -enable-experimental-deserialization-recovery %s | %FileCheck -check-prefix CHECK-SIL %s
|
||||||
@@ -30,6 +32,9 @@ let _: Int32? = useAssoc(ImportedType.self)
|
|||||||
let _: String = useAssoc(AnotherType.self) // expected-error {{cannot convert call result type '_.Assoc?' to expected type 'String'}}
|
let _: String = useAssoc(AnotherType.self) // expected-error {{cannot convert call result type '_.Assoc?' to expected type 'String'}}
|
||||||
let _: Bool? = useAssoc(AnotherType.self) // expected-error {{cannot convert value of type 'AnotherType.Assoc?' (aka 'Optional<Int32>') to specified type 'Bool?'}}
|
let _: Bool? = useAssoc(AnotherType.self) // expected-error {{cannot convert value of type 'AnotherType.Assoc?' (aka 'Optional<Int32>') to specified type 'Bool?'}}
|
||||||
let _: Int32? = useAssoc(AnotherType.self)
|
let _: Int32? = useAssoc(AnotherType.self)
|
||||||
|
|
||||||
|
let _ = wrapped // expected-error {{use of unresolved identifier 'wrapped'}}
|
||||||
|
let _ = unwrapped // okay
|
||||||
#endif // VERIFY
|
#endif // VERIFY
|
||||||
|
|
||||||
#else // TEST
|
#else // TEST
|
||||||
@@ -59,4 +64,12 @@ public let usesAssoc = useAssoc(ImportedType.self)
|
|||||||
// CHECK-RECOVERY-DAG: let usesAssoc2: AnotherType.Assoc?
|
// CHECK-RECOVERY-DAG: let usesAssoc2: AnotherType.Assoc?
|
||||||
public let usesAssoc2 = useAssoc(AnotherType.self)
|
public let usesAssoc2 = useAssoc(AnotherType.self)
|
||||||
|
|
||||||
|
|
||||||
|
// CHECK-DAG: let wrapped: WrappedInt
|
||||||
|
// CHECK-RECOVERY-NEGATIVE-NOT: let wrapped:
|
||||||
|
public let wrapped = WrappedInt(0)
|
||||||
|
// CHECK-DAG: let unwrapped: UnwrappedInt
|
||||||
|
// CHECK-RECOVERY-DAG: let unwrapped: Int32
|
||||||
|
public let unwrapped: UnwrappedInt = 0
|
||||||
|
|
||||||
#endif // TEST
|
#endif // TEST
|
||||||
|
|||||||
Reference in New Issue
Block a user