Skip to content

Commit dbd04df

Browse files
committed
Revert "[6.1][Package CMO] Prevent serializing types from SDK/system modules imported as @_implementationOnly."
This reverts commit 75d8bab.
1 parent 8502c4a commit dbd04df

File tree

2 files changed

+24
-91
lines changed

2 files changed

+24
-91
lines changed

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -784,26 +784,11 @@ bool CrossModuleOptimization::checkImports(DeclContext *ctxt) const {
784784
ModuleDecl::ImportFilter filter;
785785

786786
if (isPackageCMOEnabled(M.getSwiftModule())) {
787-
// When Package CMO is enabled, types imported with `package import`
787+
// If Package CMO is enabled, decls imported with `package import`
788788
// or `@_spiOnly import` into this module should be allowed to be
789-
// serialized. These types may be used in APIs with `package` or
790-
// higher access level, with or without `@_spi`, and such APIs should
791-
// be serializable to allow direct access by another module if it's
792-
// in the same package.
793-
//
794-
// However, types are from modules imported as `@_implementationOnly`
795-
// should not be serialized, even if their defining modules are SDK
796-
// or system modules. Since these types are intended to remain hidden
797-
// from external clients, their metadata (e.g. field offsets) may be
798-
// stripped, making it unavailable for look up at runtime. If serialized,
799-
// the client will attempt to use the serialized accessor and fail
800-
// because the metadata is missing, leading to a linker error.
801-
//
802-
// This issue applies to transitively imported types as well;
803-
// `@_implementationOnly import Foundation` imports `ObjectiveC`
804-
// indirectly, and metadata for types like `NSObject` from `ObjectiveC`
805-
// can also be stripped, thus such types should not be allowed for
806-
// serialization.
789+
// serialized. They are used in decls with `package` or higher
790+
// access level, with or without @_spi; a client of this module
791+
// should be able to access them directly if in the same package.
807792
filter = { ModuleDecl::ImportFilterKind::ImplementationOnly };
808793
} else {
809794
// See if context is imported in a "regular" way, i.e. not with
@@ -819,8 +804,17 @@ bool CrossModuleOptimization::checkImports(DeclContext *ctxt) const {
819804

820805
auto &imports = M.getSwiftModule()->getASTContext().getImportCache();
821806
for (auto &desc : results) {
822-
if (imports.isImportedBy(moduleOfCtxt, desc.importedModule))
807+
if (imports.isImportedBy(moduleOfCtxt, desc.importedModule)) {
808+
// E.g. `@_implementationOnly import QuartzCore_Private.CALayerPrivate`
809+
// imports `Foundation` as its transitive dependency module; use of a
810+
// a `public` decl in `Foundation` such as `IndexSet` in a function
811+
// signature should not block serialization in Package CMO given the
812+
// function has `package` or higher access level.
813+
if (isPackageCMOEnabled(M.getSwiftModule()) &&
814+
moduleOfCtxt->isNonUserModule())
815+
continue;
823816
return false;
817+
}
824818
}
825819
return true;
826820
}

test/SILOptimizer/package-cmo-import-filter.swift

Lines changed: 10 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
33

4-
/// 1. Test `@_implementationOnly import`.
5-
// RUN: %target-build-swift-dylib(%t/%target-library-name(Utils)) \
6-
// RUN: %t/UtilsA.swift %t/UtilsB.swift \
7-
// RUN: -module-name Utils -emit-module -package-name Pkg \
8-
// RUN: -Xfrontend -experimental-package-cmo -Xfrontend -experimental-allow-non-resilient-access \
9-
// RUN: -enable-library-evolution -O -wmo
10-
// RUN: %target-sil-opt %t/Utils.swiftmodule -I %t -sil-verify-all -o %t/Utils.sil
11-
// RUN: %FileCheck %s --check-prefix=CHECK-UTILS < %t/Utils.sil
12-
13-
/// Verify accessing PkgKlass.second from a client in a dynamic context does not cause a linker error.
14-
// RUN: %target-build-swift -I %t -L %t %t/Client.swift -package-name Pkg \
15-
// RUN: -O -wmo -enable-library-evolution \
16-
// RUN: %target-rpath(%t) -lUtils -o %t/a.out
17-
18-
// RUN: %target-swift-frontend -emit-sil -I %t -L %t %t/Client.swift \
19-
// RUN: -package-name Pkg -O -wmo -enable-library-evolution \
20-
// RUN: -lUtils -o %t/Client.sil
21-
// RUN: %FileCheck %s --check-prefix=CHECK-CLIENT < %t/Client.sil
22-
23-
/// 2. Test `package import` and `@_spiOnly import`.
244
// RUN: %target-swift-frontend %t/CoreA.swift \
255
// RUN: -module-name=CoreA -package-name Pkg \
266
// RUN: -parse-as-library -emit-module \
@@ -33,73 +13,32 @@
3313
// RUN: -emit-module-path %t/CoreB.swiftmodule -I%t \
3414
// RUN: -O -wmo -enable-library-evolution
3515

36-
// RUN: %target-swift-frontend %t/UI.swift \
37-
// RUN: -module-name=UI -package-name Pkg \
16+
// RUN: %target-swift-frontend %t/Lib.swift \
17+
// RUN: -module-name=Lib -package-name Pkg \
3818
// RUN: -parse-as-library -emit-module \
3919
// RUN: -experimental-spi-only-imports \
40-
// RUN: -emit-module-path %t/UI.swiftmodule -I %t \
20+
// RUN: -emit-module-path %t/Lib.swiftmodule -I %t \
4121
// RUN: -experimental-package-cmo -experimental-allow-non-resilient-access \
42-
// RUN: -O -wmo -enable-library-evolution -Rmodule-loading 2> %t/UI-result.txt
43-
// RUN: %target-sil-opt %t/UI.swiftmodule -I %t -sil-verify-all -o %t/UI.sil
44-
// RUN: %FileCheck %s < %t/UI.sil
22+
// RUN: -O -wmo -enable-library-evolution -Rmodule-loading 2> %t/Lib-result.txt
23+
// RUN: %target-sil-opt %t/Lib.swiftmodule -I %t -sil-verify-all -o %t/Lib.sil
24+
// RUN: %FileCheck %s < %t/Lib.sil
4525

4626
// REQUIRES: swift_in_compiler
47-
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=maccatalyst
48-
49-
//--- Client.swift
50-
package import Utils
51-
52-
package func clientFunc<T: PkgKlass>(_ list: [T]) {
53-
// closure #1 in clientFunc<A>(_:)
54-
// CHECK-CLIENT: sil private @$s6Client10clientFuncyySayxG5Utils8PkgKlassCRbzlFSo8NSObjectCxXEfU_ : $@convention(thin) <T where T : PkgKlass> (@in_guaranteed T) -> (@out NSObject, @error_indirect Never) {
55-
// CHECK-CLIENT: class_method {{.*}} #PkgKlass.second!getter : (PkgKlass) -> () -> NSObject, $@convention(method) (@guaranteed PkgKlass) -> @owned NSObject
56-
// CHECK-CLIENT: } // end sil function '$s6Client10clientFuncyySayxG5Utils8PkgKlassCRbzlFSo8NSObjectCxXEfU_'
57-
let result = list.map { $0.second }
58-
print(result)
59-
}
60-
61-
62-
//--- UtilsA.swift
63-
public import Foundation // public import to allow `NSObject` in API.
6427

65-
package class PkgKlass: NSObject {
66-
/// Serialized since it does _not_ reference a type from module imported as @_implementationOnly.
67-
// PkgKlass.first.getter
68-
// CHECK-UTILS-DAG: sil package [serialized_for_package] [canonical] @$s5Utils8PkgKlassC5firstSSvg : $@convention(method) (@guaranteed PkgKlass) -> @owned String {
69-
package var first: String
70-
71-
/// NOT serialized since it does reference a type from module imported as @_implementationOnly.
72-
// PkgKlass.second.getter
73-
// CHECK-UTILS-DAG: sil package_external [canonical] @$s5Utils8PkgKlassC6secondSo8NSObjectCvg : $@convention(method) (@guaranteed PkgKlass) -> @owned NSObject
74-
@objc package var second: NSObject
75-
76-
init(first: String, second: NSObject) {
77-
self.first = first
78-
self.second = second
79-
}
80-
}
81-
82-
//--- UtilsB.swift
83-
@_implementationOnly import Foundation
84-
85-
public func utilsFunc() {
86-
let x: NSString = "utilsfunc"
87-
print(x)
88-
}
8928

90-
//--- UI.swift
29+
//--- Lib.swift
9130
package import CoreA
9231
@_spiOnly public import CoreB
9332

9433
/// PkgStruct is imported with `package import` and should be serialized.
95-
// CHECK-DAG: sil package [serialized_for_package] [canonical] @$s2UI7libFuncyy5CoreA9PkgStructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () {
34+
// CHECK-DAG: sil package [serialized_for_package] [canonical] @$s3Lib7libFuncyy5CoreA9PkgStructVF : $@convention(thin) (@in_guaranteed PkgStruct) -> () {
9635
package func libFunc(_ arg: PkgStruct) {
9736
print(arg.pkgVar)
9837
}
9938

10039
/// PubStruct is imported with `@_spiOnly public import` and should be serialized.
101-
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s2UI7spiFuncyy5CoreB15PubStructForSPIVF : $@convention(thin) (@in_guaranteed PubStructForSPI) -> () {
102-
@_spi(GroupB)
40+
// CHECK-DAG: sil [serialized_for_package] [canonical] @$s3Lib7spiFuncyy5CoreB15PubStructForSPIVF : $@convention(thin) (@in_guaranteed PubStructForSPI) -> () {
41+
@_spi(InCoreB)
10342
public func spiFunc(_ arg: PubStructForSPI) {
10443
print(arg.pubVarForSPI)
10544
}

0 commit comments

Comments
 (0)