Skip to content

Commit 93e8a35

Browse files
committed
[Serialization] Ignore the exported module name for XRefs
Write the real module name for XRefs in swiftmodule files instead of the exported module name, from `export_as` declarations in module maps. Swiftmodule files are internal details now, they should represent the truth. We keep using the exported module name for the extensions lookup table as clients should still use the exported name. However we may need to write both alternatives in the lookup table in the future if extensions can't be found from clients not importing the exported as module. rdar://90272035
1 parent 743d82b commit 93e8a35

File tree

8 files changed

+74
-22
lines changed

8 files changed

+74
-22
lines changed

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 679; // NoAsync
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 680; // Ignore export_as in XRef
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///

lib/Serialization/Serialization.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ namespace {
203203
int32_t getNameDataForBase(const NominalTypeDecl *nominal,
204204
StringRef *dataToWrite = nullptr) {
205205
if (nominal->getDeclContext()->isModuleScopeContext())
206-
return -Serializer.addContainingModuleRef(nominal->getDeclContext());
206+
return -Serializer.addContainingModuleRef(nominal->getDeclContext(),
207+
/*ignoreExport=*/false);
207208

208209
auto &mangledName = MangledNameCache[nominal];
209210
if (mangledName.empty())
@@ -727,7 +728,8 @@ IdentifierID Serializer::addFilename(StringRef filename) {
727728
return addUniquedString(filename).second;
728729
}
729730

730-
IdentifierID Serializer::addContainingModuleRef(const DeclContext *DC) {
731+
IdentifierID Serializer::addContainingModuleRef(const DeclContext *DC,
732+
bool ignoreExport) {
731733
assert(!isa<ModuleDecl>(DC) &&
732734
"References should be to things within modules");
733735
const FileUnit *file = cast<FileUnit>(DC->getModuleScopeContext());
@@ -746,8 +748,19 @@ IdentifierID Serializer::addContainingModuleRef(const DeclContext *DC) {
746748

747749
auto exportedModuleName = file->getExportedModuleName();
748750
assert(!exportedModuleName.empty());
749-
auto exportedModuleID = M->getASTContext().getIdentifier(exportedModuleName);
750-
return addDeclBaseNameRef(exportedModuleID);
751+
auto moduleID = M->getASTContext().getIdentifier(exportedModuleName);
752+
if (ignoreExport) {
753+
auto realModuleName = M->getRealName().str();
754+
assert(!realModuleName.empty());
755+
if (realModuleName != exportedModuleName) {
756+
// Still register the exported name as it can be referenced
757+
// from the lookup tables.
758+
addDeclBaseNameRef(moduleID);
759+
760+
moduleID = M->getASTContext().getIdentifier(realModuleName);
761+
}
762+
}
763+
return addDeclBaseNameRef(moduleID);
751764
}
752765

753766
IdentifierID Serializer::addModuleRef(const ModuleDecl *module) {
@@ -1632,7 +1645,8 @@ Serializer::writeASTBlockEntity(ProtocolConformance *conformance) {
16321645
abbrCode,
16331646
addDeclRef(normal->getProtocol()),
16341647
addDeclRef(normal->getType()->getAnyNominal()),
1635-
addContainingModuleRef(normal->getDeclContext()));
1648+
addContainingModuleRef(normal->getDeclContext(),
1649+
/*ignoreExport=*/true));
16361650
}
16371651
break;
16381652
}
@@ -1831,7 +1845,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18311845
case DeclContextKind::FileUnit:
18321846
abbrCode = DeclTypeAbbrCodes[XRefLayout::Code];
18331847
XRefLayout::emitRecord(Out, ScratchRecord, abbrCode,
1834-
addContainingModuleRef(DC), pathLen);
1848+
addContainingModuleRef(DC, /*ignoreExport=*/true),
1849+
pathLen);
18351850
break;
18361851

18371852
case DeclContextKind::GenericTypeDecl: {
@@ -1883,7 +1898,8 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
18831898
genericSig = ext->getGenericSignature().getCanonicalSignature();
18841899
}
18851900
XRefExtensionPathPieceLayout::emitRecord(
1886-
Out, ScratchRecord, abbrCode, addContainingModuleRef(DC),
1901+
Out, ScratchRecord, abbrCode,
1902+
addContainingModuleRef(DC, /*ignoreExport=*/true),
18871903
addGenericSignatureRef(genericSig));
18881904
break;
18891905
}

lib/Serialization/Serialization.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,13 @@ class Serializer : public SerializerBase {
518518
/// may not be exactly the same as the name of the module containing DC;
519519
/// instead, it will match the containing file's "exported module name".
520520
///
521+
/// \param ignoreExport When true, register the real module name,
522+
/// ignoring exported_as definitions.
521523
/// \returns The ID for the identifier for the module's name, or one of the
522524
/// special module codes defined above.
523525
/// \see FileUnit::getExportedModuleName
524-
IdentifierID addContainingModuleRef(const DeclContext *DC);
526+
IdentifierID addContainingModuleRef(const DeclContext *DC,
527+
bool ignoreExport);
525528

526529
/// Records the module \m.
527530
IdentifierID addModuleRef(const ModuleDecl *m);

test/ClangImporter/private_frameworks.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,23 @@
66
// FIXME: END -enable-source-import hackaround
77

88
// Build the overlay with private frameworks.
9-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -F %S/Inputs/privateframeworks/withprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift
9+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -F %S/Inputs/privateframeworks/withprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift -enable-library-evolution -emit-module-interface-path %t/SomeKit.swiftinterface
1010

1111
// Use the overlay with private frameworks.
12-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekitcore.h -verify
12+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekitcore.h
1313

14-
// Use the overlay without private frameworks.
14+
// Using the binary overlay without private frameworks should fail.
15+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate -swift-version 4 -import-objc-header %S/Inputs/privateframeworks/bridging-somekit.h %s -verify
16+
17+
// Using an overlay rebuilt from the swiftinterface without private frameworks should work.
18+
// RUN: rm %t/SomeKit.swiftmodule
1519
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate -swift-version 4 -import-objc-header %S/Inputs/privateframeworks/bridging-somekit.h %s
1620

1721
// Build the overlay with public frameworks.
1822
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -F %S/Inputs/privateframeworks/withoutprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift
1923

2024
// Use the overlay with private frameworks.
21-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekitcore.h -verify
25+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekitcore.h
2226

2327
// Use the overlay without private frameworks.
2428
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekit.h
@@ -27,12 +31,12 @@
2731
// RUN: echo 'import private_frameworks; testErrorConformance()' > %t/main.swift
2832

2933
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t -F %S/Inputs/privateframeworks/withprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekitcore.h
30-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %t/main.swift -verify
31-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate %t/main.swift -verify
34+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %t/main.swift
35+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate %t/main.swift
3236

3337
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t -F %S/Inputs/privateframeworks/withoutprivate -swift-version 4 %s -import-objc-header %S/Inputs/privateframeworks/bridging-somekit.h
34-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %t/main.swift -verify
35-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate %t/main.swift -verify
38+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %t/main.swift
39+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate %t/main.swift
3640

3741
// REQUIRES: objc_interop
3842

@@ -42,18 +46,18 @@ func testWidget(widget: SKWidget) {
4246
widget.someObjCMethod()
4347
widget.someObjCExtensionMethod()
4448

45-
let ext = widget.extensionMethod()
49+
let ext = widget.extensionMethod() // expected-error {{value of type 'SKWidget' has no member 'extensionMethod'}}
4650
ext.foo()
4751

48-
widget.doSomethingElse(widget)
49-
inlineWidgetOperations(widget)
52+
widget.doSomethingElse(widget) // expected-error {{value of type 'SKWidget' has no member 'doSomethingElse'; did you mean 'doSomething'?}}
53+
inlineWidgetOperations(widget) // expected-error {{cannot find 'inlineWidgetOperations' in scope}}
5054

5155
let _ = widget.name
5256
}
5357

5458
func testError(widget: SKWidget) {
55-
let c: SKWidget.Error.Code = SKWidget.Error(.boom).getCode(from: widget)
56-
if c.isBoom { }
59+
let c: SKWidget.Error.Code = SKWidget.Error(.boom).getCode(from: widget) // expected-error {{value of type 'SKWidget.Error' has no member 'getCode'}}
60+
if c.isBoom { } // expected-error {{value of type 'SKWidget.Error.Code' has no member 'isBoom'}}
5761
}
5862

5963
func testGlobals() {

test/Serialization/Inputs/exported-modules/Exported.h

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct ExportedType {};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module ExportedCore [system] [extern_c] {
2+
header "ExportedCore.h"
3+
4+
export_as Exported
5+
}
6+
7+
module Exported [system] [extern_c] {
8+
header "Exported.h"
9+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// Ensure that export_as decls don't cause a deserialization failure (even one if recovered from)
2+
/// rdar://90272035
3+
4+
// RUN: %empty-directory(%t)
5+
// RUN: %target-swift-frontend -emit-module -DLIB_A %s -module-name A -emit-module-path %t/A.swiftmodule -I %t -I %S/Inputs/exported-modules
6+
// RUN: %target-swift-frontend -emit-module -DLIB_B %s -module-name B -emit-module-path %t/B.swiftmodule -I %t -I %S/Inputs/exported-modules -disable-deserialization-recovery
7+
8+
#if LIB_A
9+
import ExportedCore
10+
11+
public func foo() -> ExportedType { fatalError() }
12+
13+
#elseif LIB_B
14+
15+
import A
16+
17+
let a = foo()
18+
19+
#endif

0 commit comments

Comments
 (0)