Skip to content

Commit 0305f20

Browse files
committed
[Clang Importer] Do not rely on being able to always import Foundation on-demand
When importing Clang types. This is not an option with Explicit Module Builds. If the module being built does not (directly or transitively) depend on `Foundation`, then attempting to load it will produce an error because Implicit module loading is no longer allowed.. This change addresses a small number of cases where ClangImporter relies on being able to load `Foundation` on-demand: - When importing a single Decl from a clang module, we check whether it has certain conformances by checking all extensions of the NominalTypeDecl of the Decl in question, to see if any of the extensions contain the conformance we are looking for, but we only check extensions whose parent module is either the original module of the NominalTypeDecl or the overlay module of the NominalTypeDecl or Foundation. It seems that we do not need to actually import `Foundation` here, just checking the module Identifier should be sufficient. - In `maybeImportNSErrorOutParameter`, change the behavior to have an exit condition based on whether `Foundation` can be imported, before attempting to load it. - When checking whether or not we are allowed to bridge an Objective-C type, it also looks sufficient the query whether or not `Foundation` *can* be imported, without loading it.
1 parent 6d73abd commit 0305f20

File tree

5 files changed

+21
-11
lines changed

5 files changed

+21
-11
lines changed

include/swift/AST/Module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,9 @@ class ModuleDecl : public DeclContext, public TypeDecl {
694694
/// \returns true if this module is the "SwiftOnoneSupport" module;
695695
bool isOnoneSupportModule() const;
696696

697+
/// \returns true if this module is the "Foundation" module;
698+
bool isFoundationModule() const;
699+
697700
/// \returns true if traversal was aborted, false otherwise.
698701
bool walk(ASTWalker &Walker);
699702

lib/AST/Module.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,10 @@ bool ModuleDecl::isOnoneSupportModule() const {
13631363
return !getParent() && getName().str() == SWIFT_ONONE_SUPPORT;
13641364
}
13651365

1366+
bool ModuleDecl::isFoundationModule() const {
1367+
return !getParent() && getName() == getASTContext().Id_Foundation;
1368+
}
1369+
13661370
bool ModuleDecl::isBuiltinModule() const {
13671371
return this == getASTContext().TheBuiltinModule;
13681372
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5688,8 +5688,7 @@ namespace {
56885688
}
56895689

56905690
static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
5691-
const ProtocolDecl *proto,
5692-
ModuleDecl *foundationModule) {
5691+
const ProtocolDecl *proto) {
56935692
auto &ctx = nominal->getASTContext();
56945693

56955694
if (inheritanceListContainsProtocol(nominal, proto))
@@ -5712,7 +5711,7 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
57125711
for (ExtensionDecl *extension : nominal->getExtensions()) {
57135712
ModuleDecl *extensionModule = extension->getParentModule();
57145713
if (extensionModule != originalModule && extensionModule != overlayModule &&
5715-
extensionModule != foundationModule) {
5714+
!extensionModule->isFoundationModule()) {
57165715
continue;
57175716
}
57185717
if (inheritanceListContainsProtocol(extension, proto))
@@ -5807,8 +5806,7 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
58075806

58085807
// Break circularity by only looking for declared conformances in the
58095808
// original module, or possibly its overlay.
5810-
if (conformsToProtocolInOriginalModule(computedNominal, proto,
5811-
Impl.tryLoadFoundationModule())) {
5809+
if (conformsToProtocolInOriginalModule(computedNominal, proto)) {
58125810
synthesizedProtocols.push_back(kind);
58135811
return true;
58145812
}

lib/ClangImporter/ImportType.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,13 +1265,11 @@ static Type maybeImportNSErrorOutParameter(ClangImporter::Implementation &impl,
12651265
impl.SwiftContext.getSwiftName(KnownFoundationEntity::NSError))
12661266
return Type();
12671267

1268-
ModuleDecl *foundationModule = impl.tryLoadFoundationModule();
1269-
if (!foundationModule ||
1270-
foundationModule->getName()
1271-
!= elementClass->getModuleContext()->getName())
1268+
if (!impl.canImportFoundationModule() ||
1269+
!elementClass->getModuleContext()->isFoundationModule())
12721270
return Type();
12731271

1274-
1272+
ModuleDecl *foundationModule = impl.tryLoadFoundationModule();
12751273
if (resugarNSErrorPointer)
12761274
return impl.getNamedSwiftType(
12771275
foundationModule,
@@ -1377,7 +1375,7 @@ static ImportedType adjustTypeForConcreteImport(
13771375
// id and Any can be bridged without Foundation. There would be
13781376
// bootstrapping issues with the ObjectiveC module otherwise.
13791377
if (hint.BridgedType->isAny()
1380-
|| impl.tryLoadFoundationModule()
1378+
|| impl.canImportFoundationModule()
13811379
|| impl.ImportForwardDeclarations) {
13821380

13831381
// Set the bridged type if it wasn't done already.
@@ -2502,6 +2500,10 @@ ModuleDecl *ClangImporter::Implementation::tryLoadFoundationModule() {
25022500
ImportForwardDeclarations, checkedModules);
25032501
}
25042502

2503+
bool ClangImporter::Implementation::canImportFoundationModule() {
2504+
return SwiftContext.canImportModule({SwiftContext.Id_Foundation, SourceLoc()});
2505+
}
2506+
25052507
Type ClangImporter::Implementation::getNamedSwiftType(ModuleDecl *module,
25062508
StringRef name) {
25072509
if (!module)

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
921921
/// into the ASTContext.
922922
ModuleDecl *tryLoadFoundationModule();
923923

924+
/// Returns whether or not the "Foundation" module can be imported, without loading it.
925+
bool canImportFoundationModule();
926+
924927
/// Retrieves the Swift wrapper for the given Clang module, creating
925928
/// it if necessary.
926929
ClangModuleUnit *getWrapperForModule(const clang::Module *underlying,

0 commit comments

Comments
 (0)