[ModuleInterfaces] Add adjacent swiftmodule to dependencies

If there’s a `.swiftmodule` corresponding to the `.swiftinterface` we’re loading, but it’s out of date or otherwise unusable, still make it a dependency of the cached module.

The general assumption with cached modules is that, by virtue of them being in the cache, they have a more up-to-date view of the world than the adjacent compiled module. However, if a new `.swiftmodule` comes along that’s totally valid, we should consider it as having a newer view of the world than the cached one, so we should use it instead.

Fixes rdar://51959788
This commit is contained in:
Harlan Haskins
2019-06-20 16:47:41 -07:00
parent 33df36db20
commit b6cf719e46

View File

@@ -284,6 +284,7 @@ class swift::ParseableInterfaceBuilder {
const SourceLoc diagnosticLoc;
DependencyTracker *const dependencyTracker;
CompilerInvocation subInvocation;
SmallVector<StringRef, 3> extraDependencies;
void configureSubInvocationInputsAndOutputs(StringRef OutPath) {
auto &SubFEOpts = subInvocation.getFrontendOptions();
@@ -397,6 +398,8 @@ class swift::ParseableInterfaceBuilder {
auto DTDeps = SubInstance.getDependencyTracker()->getDependencies();
SmallVector<StringRef, 16> InitialDepNames(DTDeps.begin(), DTDeps.end());
InitialDepNames.push_back(interfacePath);
InitialDepNames.insert(InitialDepNames.end(),
extraDependencies.begin(), extraDependencies.end());
llvm::StringSet<> AllDepNames;
SmallString<128> Scratch;
@@ -487,6 +490,12 @@ public:
return subInvocation;
}
/// Ensures the requested file name is added as a dependency of the resulting
/// module.
void addExtraDependency(StringRef path) {
extraDependencies.push_back(path);
}
bool buildSwiftModule(StringRef OutPath, bool ShouldSerializeDeps,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer) {
bool SubError = false;
@@ -672,6 +681,15 @@ struct ModuleRebuildInfo {
.missingDependencies.push_back(depPath);
}
/// Determines if we saw the given module path and registered is as out of
/// date.
bool sawOutOfDateModule(StringRef modulePath) {
for (auto &mod : outOfDateModules)
if (mod.path == modulePath)
return true;
return false;
}
const char *invalidModuleReason(serialization::Status status) {
using namespace serialization;
switch (status) {
@@ -1319,6 +1337,14 @@ class ParseableInterfaceModuleLoaderImpl {
interfacePath);
}
// If we found an out-of-date .swiftmodule, we still want to add it as
// a dependency of the .swiftinterface. That way if it's updated, but
// the .swiftinterface remains the same, we invalidate the cache and
// check the new .swiftmodule, because it likely has more information
// about the state of the world.
if (rebuildInfo.sawOutOfDateModule(modulePath))
builder.addExtraDependency(modulePath);
if (builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true,
&moduleBuffer))
return std::make_error_code(std::errc::invalid_argument);