Skip to content

Commit a845fa5

Browse files
authored
Merge pull request #59383 from CodaFi/file-this-one-under-i-for-immutable
Don't Mutate ModuleDecl's File List When Creating Synthesized Files
2 parents 1a337ea + ac68360 commit a845fa5

File tree

7 files changed

+41
-39
lines changed

7 files changed

+41
-39
lines changed

include/swift/AST/FileUnit.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
5757

5858
/// Returns the synthesized file for this source file, creating one and
5959
/// inserting it into the module if it does not exist.
60-
///
61-
/// \warning Because this function mutates the parent module's list of files,
62-
/// it will invalidate the iterators of any upstream callers of
63-
/// \c ModuleDecl::getFiles().
6460
SynthesizedFileUnit &getOrCreateSynthesizedFile();
6561

6662
/// Look up a (possibly overloaded) value set at top-level scope

include/swift/AST/Module.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,15 @@ class ModuleDecl
317317
return { Files.begin(), Files.size() };
318318
}
319319

320+
/// Add the given file to this module.
321+
///
322+
/// FIXME: Remove this function from public view. Modules never need to add
323+
/// files once they are created.
324+
///
325+
/// \warning There are very few safe points to call this function once a
326+
/// \c ModuleDecl has been created. If you find yourself needing to insert
327+
/// a file in the middle of e.g. semantic analysis, use a \c
328+
/// SynthesizedFileUnit instead.
320329
void addFile(FileUnit &newFile);
321330

322331
/// Creates a map from \c #filePath strings to corresponding \c #fileID

lib/AST/Module.cpp

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,13 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
320320
FrontendStatsTracer tracer(M.getASTContext().Stats,
321321
"module-populate-cache");
322322
for (const FileUnit *file : M.getFiles()) {
323-
if (auto *SFU = dyn_cast<SynthesizedFileUnit>(file)) {
324-
addToUnqualifiedLookupCache(SFU->getTopLevelDecls(), false);
325-
continue;
326-
}
327323
auto *SF = cast<SourceFile>(file);
328324
addToUnqualifiedLookupCache(SF->getTopLevelDecls(), false);
329325
addToUnqualifiedLookupCache(SF->getHoistedDecls(), false);
326+
327+
if (auto *SFU = file->getSynthesizedFile()) {
328+
addToUnqualifiedLookupCache(SFU->getTopLevelDecls(), false);
329+
}
330330
}
331331
}
332332

@@ -548,9 +548,13 @@ SourceFile *CodeCompletionFileRequest::evaluate(Evaluator &evaluator,
548548
llvm_unreachable("Couldn't find the completion file?");
549549
}
550550

551-
#define FORWARD(name, args) \
552-
for (const FileUnit *file : getFiles()) \
553-
file->name args;
551+
#define FORWARD(name, args) \
552+
for (const FileUnit *file : getFiles()) { \
553+
file->name args; \
554+
if (auto *synth = file->getSynthesizedFile()) { \
555+
synth->name args; \
556+
} \
557+
}
554558

555559
SourceLookupCache &ModuleDecl::getSourceLookupCache() const {
556560
if (!Cache) {
@@ -3064,16 +3068,9 @@ SynthesizedFileUnit &FileUnit::getOrCreateSynthesizedFile() {
30643068
return *thisSynth;
30653069
SynthesizedFile = new (getASTContext()) SynthesizedFileUnit(*this);
30663070
SynthesizedFileAndKind.setPointer(SynthesizedFile);
3067-
// FIXME: Mutating the module in-flight is not a good idea. Any
3068-
// callers above us in the stack that are iterating over
3069-
// the module's files will have their iterators invalidated. There's
3070-
// a strong chance that whatever analysis led to this function being
3071-
// called is doing just that!
3072-
//
3073-
// Instead we ought to just call ModuleDecl::clearLookupCache() here
3074-
// and patch out the places looking for synthesized files hanging off of
3075-
// source files.
3076-
getParentModule()->addFile(*SynthesizedFile);
3071+
// Rebuild the source lookup caches now that we have a synthesized file
3072+
// full of declarations to look into.
3073+
getParentModule()->clearLookupCache();
30773074
}
30783075
return *SynthesizedFile;
30793076
}

lib/Frontend/Frontend.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,19 +1168,13 @@ bool CompilerInstance::loadPartialModulesAndImplicitImports(
11681168
bool CompilerInstance::forEachFileToTypeCheck(
11691169
llvm::function_ref<bool(SourceFile &)> fn) {
11701170
if (isWholeModuleCompilation()) {
1171-
// FIXME: Do not refactor this to use an iterator as long as
1172-
// ModuleDecl::addFile is called during Sema. Synthesized files pushed
1173-
// during semantic analysis will cause iterator invalidation here.
1174-
// See notes in SourceFile::getOrCreateSynthesizedFile() for more.
1175-
unsigned i = 0;
1176-
while (i < getMainModule()->getFiles().size()) {
1177-
auto *SF = dyn_cast<SourceFile>(getMainModule()->getFiles()[i++]);
1171+
for (auto fileName : getMainModule()->getFiles()) {
1172+
auto *SF = dyn_cast<SourceFile>(fileName);
11781173
if (!SF) {
11791174
continue;
11801175
}
11811176
if (fn(*SF))
11821177
return true;
1183-
;
11841178
}
11851179
} else {
11861180
for (auto *SF : getPrimarySourceFiles()) {

lib/IRGen/IRGen.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,8 +1096,9 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
10961096
for (auto *file : filesToEmit) {
10971097
if (auto *nextSF = dyn_cast<SourceFile>(file)) {
10981098
IGM.emitSourceFile(*nextSF);
1099-
} else if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(file)) {
1100-
IGM.emitSynthesizedFileUnit(*nextSFU);
1099+
if (auto *synthSFU = file->getSynthesizedFile()) {
1100+
IGM.emitSynthesizedFileUnit(*synthSFU);
1101+
}
11011102
} else {
11021103
file->collectLinkLibraries([&IGM](LinkLibrary LinkLib) {
11031104
IGM.addLinkLibrary(LinkLib);
@@ -1339,11 +1340,15 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
13391340

13401341
for (auto *File : M->getFiles()) {
13411342
if (auto *SF = dyn_cast<SourceFile>(File)) {
1342-
CurrentIGMPtr IGM = irgen.getGenModule(SF);
1343-
IGM->emitSourceFile(*SF);
1344-
} else if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(File)) {
1345-
CurrentIGMPtr IGM = irgen.getGenModule(nextSFU);
1346-
IGM->emitSynthesizedFileUnit(*nextSFU);
1343+
{
1344+
CurrentIGMPtr IGM = irgen.getGenModule(SF);
1345+
IGM->emitSourceFile(*SF);
1346+
}
1347+
1348+
if (auto *synthSFU = File->getSynthesizedFile()) {
1349+
CurrentIGMPtr IGM = irgen.getGenModule(synthSFU);
1350+
IGM->emitSynthesizedFileUnit(*synthSFU);
1351+
}
13471352
} else {
13481353
File->collectLinkLibraries([&](LinkLibrary LinkLib) {
13491354
irgen.getPrimaryIGM()->addLinkLibrary(LinkLib);

lib/IRGen/IRGenRequests.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ TinyPtrVector<FileUnit *> IRGenDescriptor::getFilesToEmit() const {
6868
TinyPtrVector<FileUnit *> files;
6969
files.push_back(primary);
7070

71-
if (auto *synthesizedFile = primary->getSynthesizedFile())
72-
files.push_back(synthesizedFile);
73-
7471
return files;
7572
}
7673

lib/TBDGen/TBDGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,10 @@ void TBDGenVisitor::visit(const TBDGenDescriptor &desc) {
12341234
llvm::for_each(Modules, [&](ModuleDecl *M) {
12351235
for (auto *file : M->getFiles()) {
12361236
visitFile(file);
1237+
1238+
// Visit synthesized file, if it exists.
1239+
if (auto *synthesizedFile = file->getSynthesizedFile())
1240+
visitFile(synthesizedFile);
12371241
}
12381242
});
12391243
}

0 commit comments

Comments
 (0)