Skip to content

Commit 4017416

Browse files
authored
[Serialization] Only allow loading modules during import resolution (swiftlang#21218)
Very early groundwork for private imports. Should not affect anything today.
1 parent 647c60b commit 4017416

File tree

9 files changed

+84
-10
lines changed

9 files changed

+84
-10
lines changed

include/swift/Serialization/ModuleFile.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,8 @@ class ModuleFile
589589
/// because it reads from the cursor, it is not possible to reset the cursor
590590
/// after reading. Nothing should ever follow an XREF record except
591591
/// XREF_PATH_PIECE records.
592-
llvm::Expected<Decl *> resolveCrossReference(ModuleDecl *M, uint32_t pathLen);
592+
llvm::Expected<Decl *> resolveCrossReference(serialization::ModuleID MID,
593+
uint32_t pathLen);
593594

594595
/// Populates TopLevelIDs for name lookup.
595596
void buildTopLevelDeclMap();
@@ -856,7 +857,7 @@ class ModuleFile
856857
///
857858
/// If the name matches the name of the current module, a shadowed module
858859
/// is loaded instead.
859-
ModuleDecl *getModule(ArrayRef<Identifier> name);
860+
ModuleDecl *getModule(ArrayRef<Identifier> name, bool allowLoading = false);
860861

861862
/// Returns the generic signature for the given ID.
862863
GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);

lib/Serialization/Deserialization.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ const char DeclDeserializationError::ID = '\0';
122122
void DeclDeserializationError::anchor() {}
123123
const char XRefError::ID = '\0';
124124
void XRefError::anchor() {}
125+
const char XRefNonLoadedModuleError::ID = '\0';
126+
void XRefNonLoadedModuleError::anchor() {}
125127
const char OverrideError::ID = '\0';
126128
void OverrideError::anchor() {}
127129
const char TypeError::ID = '\0';
@@ -557,6 +559,11 @@ ProtocolConformanceRef ModuleFile::readConformance(
557559
PrettyStackTraceDecl traceTo("... to", proto);
558560
auto module = getModule(moduleID);
559561

562+
// FIXME: If the module hasn't been loaded, we probably don't want to fall
563+
// back to the current module like this.
564+
if (!module)
565+
module = getAssociatedModule();
566+
560567
SmallVector<ProtocolConformance *, 2> conformances;
561568
nominal->lookupConformance(module, proto, conformances);
562569
PrettyStackTraceModuleFile traceMsg(
@@ -1229,8 +1236,14 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
12291236
}
12301237

12311238
Expected<Decl *>
1232-
ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
1239+
ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
12331240
using namespace decls_block;
1241+
1242+
ModuleDecl *baseModule = getModule(MID);
1243+
if (!baseModule) {
1244+
return llvm::make_error<XRefNonLoadedModuleError>(getIdentifier(MID));
1245+
}
1246+
12341247
assert(baseModule && "missing dependency");
12351248
PrettyXRefTrace pathTrace(*baseModule);
12361249

@@ -1550,6 +1563,10 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
15501563
GenericSignatureID rawGenericSig;
15511564
XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
15521565
M = getModule(ownerID);
1566+
if (!M) {
1567+
return llvm::make_error<XRefError>("module is not loaded",
1568+
pathTrace, getIdentifier(ownerID));
1569+
}
15531570
pathTrace.addExtension(M);
15541571

15551572
// Read the generic signature, if we have one.
@@ -1933,14 +1950,15 @@ ModuleDecl *ModuleFile::getModule(ModuleID MID) {
19331950
return getModule(getIdentifier(MID));
19341951
}
19351952

1936-
ModuleDecl *ModuleFile::getModule(ArrayRef<Identifier> name) {
1953+
ModuleDecl *ModuleFile::getModule(ArrayRef<Identifier> name,
1954+
bool allowLoading) {
19371955
if (name.empty() || name.front().empty())
19381956
return getContext().TheBuiltinModule;
19391957

19401958
// FIXME: duplicated from NameBinder::getModule
19411959
if (name.size() == 1 &&
19421960
name.front() == FileContext->getParentModule()->getName()) {
1943-
if (!ShadowedModule) {
1961+
if (!ShadowedModule && allowLoading) {
19441962
auto importer = getContext().getClangModuleLoader();
19451963
assert(importer && "no way to import shadowed module");
19461964
ShadowedModule = importer->loadModule(SourceLoc(),
@@ -1953,7 +1971,10 @@ ModuleDecl *ModuleFile::getModule(ArrayRef<Identifier> name) {
19531971
SmallVector<ImportDecl::AccessPathElement, 4> importPath;
19541972
for (auto pathElem : name)
19551973
importPath.push_back({ pathElem, SourceLoc() });
1956-
return getContext().getModule(importPath);
1974+
1975+
if (allowLoading)
1976+
return getContext().getModule(importPath);
1977+
return getContext().getLoadedModule(importPath);
19571978
}
19581979

19591980

@@ -4038,7 +4059,7 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) {
40384059
ModuleID baseModuleID;
40394060
uint32_t pathLen;
40404061
decls_block::XRefLayout::readRecord(scratch, baseModuleID, pathLen);
4041-
auto resolved = resolveCrossReference(getModule(baseModuleID), pathLen);
4062+
auto resolved = resolveCrossReference(baseModuleID, pathLen);
40424063
if (!resolved)
40434064
return resolved;
40444065
declOrOffset = resolved.get();

lib/Serialization/DeserializationErrors.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,26 @@ class XRefError : public llvm::ErrorInfo<XRefError, DeclDeserializationError> {
282282
}
283283
};
284284

285+
class XRefNonLoadedModuleError :
286+
public llvm::ErrorInfo<XRefNonLoadedModuleError, DeclDeserializationError> {
287+
friend ErrorInfo;
288+
static const char ID;
289+
void anchor() override;
290+
291+
public:
292+
explicit XRefNonLoadedModuleError(Identifier name) {
293+
this->name = name;
294+
}
295+
296+
void log(raw_ostream &OS) const override {
297+
OS << "module '" << name << "' was not loaded";
298+
}
299+
300+
std::error_code convertToErrorCode() const override {
301+
return llvm::inconvertibleErrorCode();
302+
}
303+
};
304+
285305
class OverrideError : public llvm::ErrorInfo<OverrideError,
286306
DeclDeserializationError> {
287307
private:

lib/Serialization/ModuleFile.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,8 @@ class ModuleFile::ExtensionTableInfo {
455455
StringRef moduleNameOrMangledBase;
456456
if (nameIDOrLength < 0) {
457457
const ModuleDecl *module = File.getModule(-nameIDOrLength);
458-
moduleNameOrMangledBase = module->getName().str();
458+
if (module)
459+
moduleNameOrMangledBase = module->getName().str();
459460
} else {
460461
moduleNameOrMangledBase =
461462
StringRef(reinterpret_cast<const char *>(data), nameIDOrLength);
@@ -1497,7 +1498,7 @@ Status ModuleFile::associateWithFileContext(FileUnit *file,
14971498
assert(!modulePath.back().empty() &&
14981499
"invalid module name (submodules not yet supported)");
14991500
}
1500-
auto module = getModule(modulePath);
1501+
auto module = getModule(modulePath, /*allowLoading*/true);
15011502
if (!module || module->failedToLoad()) {
15021503
// If we're missing the module we're shadowing, treat that specially.
15031504
if (modulePath.size() == 1 &&
@@ -1735,7 +1736,7 @@ void ModuleFile::getImportDecls(SmallVectorImpl<Decl *> &Results) {
17351736
if (AccessPath.size() == 1 && AccessPath[0].first == Ctx.StdlibModuleName)
17361737
continue;
17371738

1738-
ModuleDecl *M = Ctx.getModule(AccessPath);
1739+
ModuleDecl *M = Ctx.getLoadedModule(AccessPath);
17391740

17401741
auto Kind = ImportKind::Module;
17411742
if (!ScopePath.empty()) {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#if !BAD
2+
# import <IndirectlyImported.h>
3+
#endif
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
struct IndirectlyImportedStruct {
2+
int value;
3+
};

test/Serialization/Recovery/Inputs/custom-modules/module.modulemap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
module IndirectImport {
2+
header "IndirectImport.h"
3+
export *
4+
}
5+
module IndirectlyImported {
6+
header "IndirectlyImported.h"
7+
}
8+
19
module Overrides { header "Overrides.h" }
210
module ProtocolInheritance { header "ProtocolInheritance.h" }
311
module RenameAcrossVersions { header "RenameAcrossVersions.h" }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules %s
3+
4+
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
5+
6+
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DBAD | %FileCheck -check-prefix CHECK-RECOVERY %s
7+
8+
import IndirectImport
9+
10+
// CHECK: func baseline()
11+
// CHECK-RECOVERY: func baseline()
12+
public func baseline() {}
13+
14+
// CHECK: func test(_: IndirectlyImportedStruct)
15+
// CHECK-RECOVERY-NOT: IndirectlyImportedStruct
16+
public func test(_: IndirectlyImportedStruct) {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
module ObjCLib {
22
header "ObjCLib.h"
3+
export *
34
}

0 commit comments

Comments
 (0)