Skip to content

Frontend: Add a rebuild diagnostic explaining why the adjacent swiftmodule was ignored #63688

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,11 @@ REMARK(rebuilding_module_from_interface,none,
NOTE(sdk_version_pbm_version,none,
"SDK build version is '%0'; prebuilt modules were "
"built using SDK build version: '%1'", (StringRef, StringRef))
NOTE(compiled_module_ignored_reason,none,
"compiled module '%0' was ignored because %select{%error"
"|it belongs to a framework in the SDK"
"|loading from module interfaces is prefered}1",
(StringRef, unsigned))
NOTE(out_of_date_module_here,none,
"%select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1'",
(unsigned, StringRef))
Expand Down
59 changes: 44 additions & 15 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,54 +223,73 @@ struct ModuleRebuildInfo {
Forwarding,
Prebuilt
};
struct OutOfDateModule {
enum class ReasonIgnored {
NotIgnored,
PublicFramework,
InterfacePreferred,
};
struct CandidateModule {
std::string path;
Optional<serialization::Status> serializationStatus;
ModuleKind kind;
ReasonIgnored reasonIgnored;
SmallVector<std::string, 10> outOfDateDependencies;
SmallVector<std::string, 10> missingDependencies;
};
SmallVector<OutOfDateModule, 3> outOfDateModules;
SmallVector<CandidateModule, 3> candidateModules;

OutOfDateModule &getOrInsertOutOfDateModule(StringRef path) {
for (auto &mod : outOfDateModules) {
CandidateModule &getOrInsertCandidateModule(StringRef path) {
for (auto &mod : candidateModules) {
if (mod.path == path) return mod;
}
outOfDateModules.push_back({path.str(), None, ModuleKind::Normal, {}, {}});
return outOfDateModules.back();
candidateModules.push_back({path.str(),
None,
ModuleKind::Normal,
ReasonIgnored::NotIgnored,
{},
{}});
return candidateModules.back();
}

/// Sets the kind of a module that failed to load.
void setModuleKind(StringRef path, ModuleKind kind) {
getOrInsertOutOfDateModule(path).kind = kind;
getOrInsertCandidateModule(path).kind = kind;
}

/// Sets the serialization status of the module at \c path. If this is
/// anything other than \c Valid, a note will be added stating why the module
/// was invalid.
void setSerializationStatus(StringRef path, serialization::Status status) {
getOrInsertOutOfDateModule(path).serializationStatus = status;
getOrInsertCandidateModule(path).serializationStatus = status;
}

/// Registers an out-of-date dependency at \c depPath for the module
/// at \c modulePath.
void addOutOfDateDependency(StringRef modulePath, StringRef depPath) {
getOrInsertOutOfDateModule(modulePath)
getOrInsertCandidateModule(modulePath)
.outOfDateDependencies.push_back(depPath.str());
}

/// Registers a missing dependency at \c depPath for the module
/// at \c modulePath.
void addMissingDependency(StringRef modulePath, StringRef depPath) {
getOrInsertOutOfDateModule(modulePath)
getOrInsertCandidateModule(modulePath)
.missingDependencies.push_back(depPath.str());
}

/// Sets the reason that the module at \c path was ignored. If this is
/// anything besides \c NotIgnored a note will be added stating why the module
/// was ignored.
void addIgnoredModule(StringRef modulePath, ReasonIgnored reasonIgnored) {
getOrInsertCandidateModule(modulePath).reasonIgnored = reasonIgnored;
}

/// 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)
for (auto &mod : candidateModules)
if (mod.path == modulePath &&
mod.reasonIgnored == ReasonIgnored::NotIgnored)
return true;
return false;
}
Expand Down Expand Up @@ -310,9 +329,15 @@ struct ModuleRebuildInfo {
}
// We may have found multiple failing modules, that failed for different
// reasons. Emit a note for each of them.
for (auto &mod : outOfDateModules) {
diags.diagnose(loc, diag::out_of_date_module_here,
(unsigned)mod.kind, mod.path);
for (auto &mod : candidateModules) {
// If a the compiled module was ignored, diagnose the reason.
if (mod.reasonIgnored != ReasonIgnored::NotIgnored) {
diags.diagnose(loc, diag::compiled_module_ignored_reason, mod.path,
(unsigned)mod.reasonIgnored);
} else {
diags.diagnose(loc, diag::out_of_date_module_here, (unsigned)mod.kind,
mod.path);
}

// Diagnose any out-of-date dependencies in this module.
for (auto &dep : mod.outOfDateDependencies) {
Expand Down Expand Up @@ -677,6 +702,7 @@ class ModuleInterfaceLoaderImpl {
}

std::pair<std::string, std::string> getCompiledModuleCandidates() {
using ReasonIgnored = ModuleRebuildInfo::ReasonIgnored;
std::pair<std::string, std::string> result;
// Should we attempt to load a swiftmodule adjacent to the swiftinterface?
bool shouldLoadAdjacentModule = !ctx.IgnoreAdjacentModules;
Expand All @@ -690,6 +716,7 @@ class ModuleInterfaceLoaderImpl {
if (!ctx.SearchPathOpts.getSDKPath().empty() &&
modulePath.startswith(publicFrameworksPath)) {
shouldLoadAdjacentModule = false;
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::PublicFramework);
}

switch (loadMode) {
Expand All @@ -702,6 +729,8 @@ class ModuleInterfaceLoaderImpl {
// skip the module adjacent to the interface, but use the caches if
// they're present.
shouldLoadAdjacentModule = false;
rebuildInfo.addIgnoredModule(modulePath,
ReasonIgnored::InterfacePreferred);
break;
case ModuleLoadingMode::PreferSerialized:
// The rest of the function should be covered by this.
Expand Down
1 change: 1 addition & 0 deletions test/ModuleInterface/ignore-adjacent-swiftmodules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// RUN: -verify -Rmodule-interface-rebuild

import PublicSwift // expected-remark {{rebuilding module 'PublicSwift' from interface}}
// expected-note @-1 {{was ignored because it belongs to a framework in the SDK}}

// The private adjacent module under PrivateFrameworks should still be tried first, and then rebuilt.
import PrivateSwift
Expand Down