Skip to content

Commit 3f5cb3d

Browse files
committed
Currently it errors when loading a module built from interface if it has package-name.
This disallows building an interface file that imports such module which should be allowed since interface does not contain package symbols unless usableFromInline or inlinable. This change limits erroring only when building a .swift file. Resolves rdar://108633068
1 parent f9701df commit 3f5cb3d

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)