Skip to content

Commit 5bf8f62

Browse files
authored
Merge pull request #65854 from apple/es-rel-interface
[5.9] Limit loading error when importing a module with package name built from interface
2 parents c4e8f67 + ffa6ebd commit 5bf8f62

File tree

4 files changed

+278
-10
lines changed

4 files changed

+278
-10
lines changed

lib/Sema/ImportResolution.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct UnboundImport {
138138
void validateResilience(NullablePtr<ModuleDecl> topLevelModule,
139139
SourceFile &SF);
140140
void validateAllowableClient(ModuleDecl *topLevelModule, SourceFile &SF);
141+
void validateInterfaceWithPackageName(ModuleDecl *topLevelModule, SourceFile &SF);
141142

142143
/// Diagnoses an inability to import \p modulePath in this situation and, if
143144
/// \p attrs is provided and has an \p attrKind, invalidates the attribute and
@@ -652,8 +653,8 @@ void UnboundImport::validateOptions(NullablePtr<ModuleDecl> topLevelModule,
652653
validateTestable(top);
653654
validatePrivate(top);
654655
validateAllowableClient(top, SF);
656+
validateInterfaceWithPackageName(top, SF);
655657
}
656-
657658
validateResilience(topLevelModule, SF);
658659
}
659660

@@ -756,6 +757,28 @@ void UnboundImport::validateAllowableClient(ModuleDecl *importee,
756757
}
757758
}
758759

760+
void UnboundImport::validateInterfaceWithPackageName(ModuleDecl *topLevelModule,
761+
SourceFile &SF) {
762+
assert(topLevelModule);
763+
764+
// If current source file is interface, don't throw an error
765+
if (SF.Kind == SourceFileKind::Interface)
766+
return;
767+
768+
// If source file is .swift or non-interface, show diags when importing an interface file
769+
ASTContext &ctx = topLevelModule->getASTContext();
770+
if (!topLevelModule->getPackageName().empty() &&
771+
topLevelModule->getPackageName().str() == ctx.LangOpts.PackageName &&
772+
topLevelModule->isBuiltFromInterface()) {
773+
ctx.Diags.diagnose(SourceLoc(),
774+
diag::in_package_module_not_compiled_from_source,
775+
topLevelModule->getBaseIdentifier(),
776+
ctx.LangOpts.PackageName,
777+
topLevelModule->getModuleSourceFilename()
778+
);
779+
}
780+
}
781+
759782
void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
760783
SourceFile &SF) {
761784
if (import.options.contains(ImportFlags::ImplementationOnly) ||

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -825,15 +825,6 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
825825
if (loadedModuleFile->isConcurrencyChecked())
826826
M.setIsConcurrencyChecked();
827827
if (!loadedModuleFile->getModulePackageName().empty()) {
828-
if (loadedModuleFile->isBuiltFromInterface() &&
829-
loadedModuleFile->getModulePackageName().str() == Ctx.LangOpts.PackageName) {
830-
Ctx.Diags.diagnose(SourceLoc(),
831-
diag::in_package_module_not_compiled_from_source,
832-
M.getBaseIdentifier(),
833-
Ctx.LangOpts.PackageName,
834-
loadedModuleFile->getModuleSourceFilename()
835-
);
836-
}
837828
M.setPackageName(Ctx.getIdentifier(loadedModuleFile->getModulePackageName()));
838829
}
839830
M.setUserModuleVersion(loadedModuleFile->getUserModuleVersion());
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// TEST Build Dep with package symbols
5+
// RUN: %target-swift-frontend -emit-module %t/Dep.swift \
6+
// RUN: -module-name Dep -swift-version 5 -I %t \
7+
// RUN: -package-name myPkg \
8+
// RUN: -enable-library-evolution \
9+
// RUN: -emit-module-path %t/Dep.swiftmodule \
10+
// RUN: -emit-module-interface-path %t/Dep.swiftinterface \
11+
// RUN: -emit-private-module-interface-path %t/Dep.private.swiftinterface
12+
13+
// TEST Dep private interface should contain the package name
14+
// RUN: %target-swift-typecheck-module-from-interface(%t/Dep.private.swiftinterface) -module-name Dep -I %t
15+
// RUN: %FileCheck %s --check-prefix=CHECK-DEP-PRIVATE < %t/Dep.private.swiftinterface
16+
// CHECK-DEP-PRIVATE: -package-name myPkg
17+
18+
// TEST Dep.swiftmodule should contain package name and package symbols
19+
// RUN: llvm-bcanalyzer --dump %t/Dep.swiftmodule | %FileCheck %s --check-prefix=CHECK-DEP-BC
20+
// CHECK-DEP-BC: <MODULE_PACKAGE_NAME abbrevid=6/> blob data = 'myPkg'
21+
22+
// TEST Lib should load Dep.swiftmodule and access package decls if in the same package and error if not
23+
24+
// RUN: %target-swift-frontend -typecheck %t/Lib.swift -package-name myPkg -I %t -verify
25+
26+
// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -package-name otherPkg -I %t -Rmodule-loading 2> %t/result-binary-other-pkg.output
27+
// RUN: %FileCheck %s --check-prefix=CHECK-DIFF-PKG < %t/result-binary-other-pkg.output
28+
29+
// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -I %t -Rmodule-loading 2> %t/result-binary-no-pkg.output
30+
// RUN: %FileCheck %s --check-prefix=CHECK-DIFF-PKG < %t/result-binary-no-pkg.output
31+
32+
// CHECK-DIFF-PKG: remark: loaded module 'Dep'
33+
// CHECK-DIFF-PKG: error: cannot find 'packageFuncInlinable' in scope
34+
// CHECK-DIFF-PKG: error: cannot find 'packageFunc' in scope
35+
// CHECK-DIFF-PKG: error: cannot find 'PackageKlassUFI' in scope
36+
37+
// TEST Remove Dep binary and build it from interface
38+
// RUN: rm %t/Dep.swiftmodule
39+
// RUN: %target-swift-frontend -compile-module-from-interface %t/Dep.private.swiftinterface \
40+
// RUN: -module-name Dep -I %t \
41+
// RUN: -o %t/Dep.swiftmodule
42+
43+
// TEST Dep binary built from interface should contain package name but no package symbols
44+
// RUN: llvm-bcanalyzer --dump %t/Dep.swiftmodule | %FileCheck %s --check-prefix=CHECK-DEP-INTER-BC
45+
// CHECK-DEP-INTER-BC: <MODULE_PACKAGE_NAME abbrevid=7/> blob data = 'myPkg'
46+
47+
// TEST Lib should error on loading Dep built from interface and accessing package symbols (unless usableFromInline or inlinable)
48+
// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -package-name myPkg -I %t 2> %t/result-access.output
49+
// RUN: %FileCheck %s --check-prefix CHECK-LIB < %t/result-access.output
50+
// CHECK-LIB: error: module 'Dep' is in package 'myPkg' but was built from interface; modules of the same package can only be loaded if built from source
51+
// CHECK-LIB: error: cannot find 'packageFunc' in scope
52+
// CHECK-LIB: error: value of type 'PackageKlassUFI' has no member 'packageVar'
53+
54+
// TEST Remove and rebuild Dep from source
55+
// RUN: rm %t/Dep.swiftmodule
56+
// RUN: %target-swift-frontend -emit-module %t/Dep.swift \
57+
// RUN: -module-name Dep -swift-version 5 -I %t \
58+
// RUN: -package-name myPkg \
59+
// RUN: -enable-library-evolution \
60+
// RUN: -emit-module-path %t/Dep.swiftmodule
61+
62+
// TEST Build LibPass with package name
63+
// RUN: %target-swift-frontend -emit-module %t/LibPass.swift \
64+
// RUN: -module-name LibPass -swift-version 5 -I %t \
65+
// RUN: -package-name myPkg \
66+
// RUN: -enable-library-evolution \
67+
// RUN: -emit-module-path %t/LibPass.swiftmodule \
68+
// RUN: -emit-module-interface-path %t/LibPass.swiftinterface \
69+
// RUN: -emit-private-module-interface-path %t/LibPass.private.swiftinterface
70+
71+
// TEST Loading LibPass and accessing lib func should pass
72+
// RUN: %target-swift-frontend -typecheck %t/Client.swift -package-name myPkg -I %t -verify
73+
74+
// TEST Building LibPass from interface with Dep (built from interface) should succeed with or without package name
75+
// Without package name
76+
// RUN: rm %t/Dep.swiftmodule
77+
// RUN: rm %t/LibPass.swiftmodule
78+
// RUN: %target-swift-frontend -compile-module-from-interface %t/LibPass.private.swiftinterface \
79+
// RUN: -module-name LibPass -I %t \
80+
// RUN: -o %t/LibPass.swiftmodule
81+
82+
// With package name
83+
// RUN: rm %t/LibPass.swiftmodule
84+
// RUN: %target-swift-frontend -compile-module-from-interface %t/LibPass.private.swiftinterface \
85+
// RUN: -module-name LibPass -I %t \
86+
// RUN: -package-name myPkg \
87+
// RUN: -o %t/LibPass.swiftmodule
88+
89+
90+
//--- Dep.swift
91+
@usableFromInline
92+
package class PackageKlassUFI {
93+
@usableFromInline package init() {}
94+
@usableFromInline package var packageVarUFI: String = "pkgUFI"
95+
package var packageVar: String = "pkg"
96+
}
97+
98+
package func packageFunc() {
99+
print("package func")
100+
}
101+
102+
@inlinable
103+
package func packageFuncInlinable() {
104+
print("inlinable package func")
105+
}
106+
107+
public func publicFunc() {
108+
print("public func")
109+
}
110+
111+
@inlinable
112+
public func publicFuncInlinable() {
113+
print("inlinable public func")
114+
}
115+
116+
//--- Lib.swift
117+
import Dep
118+
119+
public func libFunc() {
120+
publicFuncInlinable()
121+
publicFunc()
122+
packageFuncInlinable()
123+
packageFunc()
124+
let x = PackageKlassUFI()
125+
let y = x.packageVarUFI
126+
let z = x.packageVar
127+
print(x, y, z)
128+
}
129+
130+
131+
//--- LibPass.swift
132+
import Dep
133+
134+
public func libFunc() {
135+
publicFuncInlinable()
136+
publicFunc()
137+
packageFuncInlinable()
138+
let x = PackageKlassUFI()
139+
let y = x.packageVarUFI
140+
print(x, y)
141+
}
142+
143+
144+
//--- Client.swift
145+
import LibPass
146+
147+
public func clientFunc() {
148+
libFunc()
149+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// REQUIRES: VENDOR=apple
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %empty-directory(%t.mod)
5+
// RUN: %empty-directory(%t.sdk)
6+
// RUN: %empty-directory(%t.module-cache)
7+
// RUN: split-file %s %t
8+
9+
// Make sure api-digester loads an interface with package-name correctly
10+
11+
// Generate module Lib
12+
// RUN: %target-swift-frontend %t/Lib.swift -emit-module -module-name Lib -emit-module-path %t.mod/Lib.swiftmodule -emit-module-interface-path %t.mod/Lib.swiftinterface -emit-private-module-interface-path %t.mod/Lib.private.swiftinterface -package-name myLib -parse-as-library -enable-library-evolution -module-cache-path %t.module-cache -swift-version 5
13+
14+
// Dumping sdk for Lib ABI via .swiftmodule file should work
15+
// RUN: %api-digester -dump-sdk -abort-on-module-fail -abi -module Lib -o - -module-cache-path %t.module-cache -I %t.mod > %t.dump-lib-binary.json
16+
// RUN: %FileCheck -check-prefix=LIB-BINARY %s < %t.dump-lib-binary.json
17+
// LIB-BINARY: PkgKlass
18+
// LIB-BINARY: pkgFunc
19+
// LIB-BINARY: PublicStruct
20+
// LIB-BINARY: PkgKlassUFI
21+
// LIB-BINARY: libFunc
22+
23+
// Dumping sdk file for Lib ABI via .swiftinterface file should work
24+
// RUN: %api-digester -dump-sdk -abort-on-module-fail -abi -module Lib -use-interface-for-module Lib -o - -module-cache-path %t.module-cache -I %t.mod > %t.dump-lib-interface.json
25+
// RUN: %FileCheck -check-prefix=LIB-INTERFACE %s < %t.dump-lib-interface.json
26+
// LIB-INTERFACE-NOT: PkgKlass
27+
// LIB-INTERFACE-NOT: pkgFunc
28+
// LIB-INTERFACE: PublicStruct
29+
// LIB-INTERFACE: PkgKlassUFI
30+
// LIB-INTERFACE: libFunc
31+
32+
// Generate module Client
33+
// RUN: %target-swift-frontend %t/Client.swift -emit-module -module-name Client -emit-module-path %t.mod/Client.swiftmodule -emit-module-interface-path %t.mod/Client.swiftinterface -emit-private-module-interface-path %t.mod/Client.private.swiftinterface -package-name myLib -parse-as-library -enable-library-evolution -module-cache-path %t.module-cache -swift-version 5 -I %t.mod
34+
35+
// RUN: rm -f %t.mod/Lib.swiftmodule
36+
// RUN: rm -f %t.module-cache/Lib*.swiftmodule
37+
38+
// Dumping sdk for Client ABI via .swiftmodule file should work
39+
// RUN: %api-digester -dump-sdk -abort-on-module-fail -abi -module Client -o - -module-cache-path %t.module-cache -I %t.mod > %t.dump-client-binary.json
40+
// RUN: %FileCheck -check-prefix=CLIENT-BINARY %s < %t.dump-client-binary.json
41+
// CLIENT-BINARY-NOT: PkgKlass
42+
// CLIENT-BINARY-NOT: pkgFunc
43+
// CLIENT-BINARY-NOT: PublicStruct
44+
// CLIENT-BINARY-NOT: PkgKlassUFI
45+
// CLIENT-BINARY-NOT: libFunc
46+
// CLIENT-BINARY: clientFunc
47+
// CLIENT-BINARY: clientFuncInlinable
48+
49+
// Dumping sdk for Client ABI via .swiftinterface file should work
50+
// RUN: %api-digester -dump-sdk -abort-on-module-fail -abi -module Client -use-interface-for-module Client -o - -module-cache-path %t.module-cache -I %t.mod > %t.dump-client-interface.json
51+
// RUN: %FileCheck -check-prefix=CLIENT-INTERFACE %s < %t.dump-client-interface.json
52+
// CLIENT-INTERFACE-NOT: PkgKlass
53+
// CLIENT-INTERFACE-NOT: pkgFunc
54+
// CLIENT-INTERFACE-NOT: PublicStruct
55+
// CLIENT-INTERFACE-NOT: PkgKlassUFI
56+
// CLIENT-INTERFACE-NOT: libFunc
57+
// CLIENT-INTERFACE: clientFunc
58+
// CLIENT-INTERFACE: clientFuncInlinable
59+
60+
61+
//--- Lib.swift
62+
package class PkgKlass {
63+
package class func foo() {}
64+
package func foo2(_ : Int) {}
65+
package weak var bar : PkgKlass?
66+
package var bar2 : PkgKlass?
67+
}
68+
69+
package func pkgFunc() -> (PkgKlass) -> () { return { _ in } }
70+
71+
public struct PublicStruct {
72+
package init(_ : PkgKlass?) {}
73+
public static func baz(_ arg: String?) {}
74+
}
75+
76+
@usableFromInline
77+
package struct PkgKlassUFI {
78+
@usableFromInline
79+
package init() {}
80+
@usableFromInline
81+
package func ufiFunc() {}
82+
}
83+
84+
@inlinable
85+
public func libFunc() {
86+
PkgKlassUFI().ufiFunc()
87+
}
88+
89+
//--- Client.swift
90+
import Lib
91+
92+
public func clientFunc() {
93+
PkgKlass.foo()
94+
let result = pkgFunc()
95+
let s = PublicStruct(nil)
96+
PublicStruct.baz("")
97+
print(s, result)
98+
}
99+
100+
@inlinable
101+
public func clientFuncInlinable() {
102+
let x = PkgKlassUFI()
103+
libFunc()
104+
print(x)
105+
}

0 commit comments

Comments
 (0)