[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:
Jordan Rose
2017-04-26 17:47:19 -07:00
parent 10c62545c8
commit 1168cacf4f
7 changed files with 158 additions and 50 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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());
}
} }
} }

View File

@@ -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);

View File

@@ -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

View File

@@ -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