[Serialization] Handle re-export of error enums mapped via import-as-member.

Thanks to Jordan for coming up with the right combination of features to
trigger this code path.
This commit is contained in:
Doug Gregor
2017-09-15 16:58:26 -07:00
parent fc20debc36
commit e3207f753c
6 changed files with 34 additions and 15 deletions

View File

@@ -24,6 +24,7 @@
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/BCReadingExtras.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Basic/Defer.h"
@@ -1098,6 +1099,23 @@ getActualCtorInitializerKind(uint8_t raw) {
return None;
}
/// Determine whether the two modules are re-exported to the same module.
static bool reExportedToSameModule(const ModuleDecl *fromModule,
const ModuleDecl *toModule) {
auto fromClangModule
= dyn_cast<ClangModuleUnit>(fromModule->getFiles().front());
if (!fromClangModule)
return false;
auto toClangModule
= dyn_cast<ClangModuleUnit>(toModule->getFiles().front());
if (!toClangModule)
return false;
return fromClangModule->getExportedModuleName() ==
toClangModule->getExportedModuleName();
}
/// Remove values from \p values that don't match the expected type or module.
///
/// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
@@ -1130,7 +1148,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
// FIXME: Should be able to move a value from an extension in a derived
// module to the original definition in a base module.
if (expectedModule && !value->hasClangNode() &&
value->getModuleContext() != expectedModule)
value->getModuleContext() != expectedModule &&
!reExportedToSameModule(value->getModuleContext(), expectedModule))
return true;
// If we're expecting a member within a constrained extension with a

View File

@@ -37,7 +37,6 @@
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/SerializationOptions.h"
#include "clang/Basic/Module.h"
// FIXME: We're just using CompilerInstance::createOutputFile.
// This API should be sunk down to LLVM.
#include "clang/Frontend/CompilerInstance.h"
@@ -533,13 +532,14 @@ IdentifierID Serializer::addModuleRef(const ModuleDecl *M) {
// If we're referring to a member of a private module that will be
// re-exported via a public module, record the public module's name.
if (auto clangModule = M->findUnderlyingClangModule()) {
if (!clangModule->ExportAsModule.empty()) {
auto publicModuleName =
M->getASTContext().getIdentifier(clangModule->ExportAsModule);
return addDeclBaseNameRef(publicModuleName);
}
if (auto clangModuleUnit =
dyn_cast<ClangModuleUnit>(M->getFiles().front())) {
auto exportedModuleName =
M->getASTContext().getIdentifier(
clangModuleUnit->getExportedModuleName());
return addDeclBaseNameRef(exportedModuleName);
}
assert(!M->getName().empty());
return addDeclBaseNameRef(M->getName());
}

View File

@@ -15,13 +15,13 @@ extension NSObject {
public func doSomethingElse(_: SKWidget) { }
}
extension SKWidgetError {
public func getCode(from widget: SKWidget) -> SKWidgetError.Code {
extension SKWidget.Error {
public func getCode(from widget: SKWidget) -> SKWidget.Error.Code {
return widget.getCurrentError()
}
}
extension SKWidgetError.Code {
extension SKWidget.Error.Code {
public var isBoom: Bool {
return self == .boom
}
@@ -42,7 +42,7 @@ public func inlineWidgetOperations(_ widget: SKWidget) {
widget.doSomethingElse(widget)
let obj = widget.anObject
widget.anObject = obj
_ = SKWidgetError(.boom).getCode(from: widget).isBoom
_ = SKWidget.Error(.boom).getCode(from: widget).isBoom
var hao: HasAnObject = widget
someKitGlobalFunc()
hao.anObject = widget

View File

@@ -14,7 +14,7 @@
@end
extern NSString * _Nonnull const SKWidgetErrorDomain;
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) SKWidgetErrorCode : NSInteger {
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
SKWidgetErrorNone = 0,
SKWidgetErrorBoom = 1
} SKWidgetErrorCode;

View File

@@ -15,7 +15,7 @@
@end
extern NSString * _Nonnull const SKWidgetErrorDomain;
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) SKWidgetErrorCode : NSInteger {
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
SKWidgetErrorNone = 0,
SKWidgetErrorBoom = 1
} SKWidgetErrorCode;

View File

@@ -40,7 +40,7 @@ func testWidget(widget: SKWidget) {
}
func testError(widget: SKWidget) {
let c: SKWidgetError.Code = SKWidgetError(.boom).getCode(from: widget)
let c: SKWidget.Error.Code = SKWidget.Error(.boom).getCode(from: widget)
if c.isBoom { }
}