Skip to content

Commit 2941051

Browse files
authored
Merge pull request #65481 from apple/es-pkg-import
Limit loading error when importing a module built from interface with package-name
2 parents c217106 + ceb2884 commit 2941051

File tree

3 files changed

+173
-10
lines changed

3 files changed

+173
-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+
}

0 commit comments

Comments
 (0)