Skip to content

[Frontend] Ignore adjacent swiftmodule in compiler host modules #66576

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
Jun 14, 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
3 changes: 2 additions & 1 deletion include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ NOTE(sdk_version_pbm_version,none,
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 preferred}1",
"|loading from module interfaces is preferred"
"|it's a compiler host module}1",
(StringRef, unsigned))
NOTE(out_of_date_module_here,none,
"%select{compiled|cached|forwarding|prebuilt}0 module is out of date: '%1'",
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Basic/StringExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ class NullTerminatedStringRef {
/// where escaped Unicode characters lead to malformed/invalid JSON.
void writeEscaped(llvm::StringRef Str, llvm::raw_ostream &OS);

/// Whether the path components of `path` begin with those from `prefix`.
bool pathStartsWith(StringRef prefix, StringRef path);

} // end namespace swift

#endif // SWIFT_BASIC_STRINGEXTRAS_H
16 changes: 3 additions & 13 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "swift/Basic/Compiler.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Statistic.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Parse/Token.h"
#include "swift/Strings.h"
Expand Down Expand Up @@ -4235,18 +4236,6 @@ FrontendStatsTracer::getTraceFormatter<const SourceFile *>() {
return &TF;
}

static bool prefixMatches(StringRef prefix, StringRef path) {
auto prefixIt = llvm::sys::path::begin(prefix),
prefixEnd = llvm::sys::path::end(prefix);
for (auto pathIt = llvm::sys::path::begin(path),
pathEnd = llvm::sys::path::end(path);
prefixIt != prefixEnd && pathIt != pathEnd; ++prefixIt, ++pathIt) {
if (*prefixIt != *pathIt)
return false;
}
return prefixIt == prefixEnd;
}

bool IsNonUserModuleRequest::evaluate(Evaluator &evaluator, ModuleDecl *mod) const {
// stdlib is non-user by definition
if (mod->isStdlibModule())
Expand Down Expand Up @@ -4274,5 +4263,6 @@ bool IsNonUserModuleRequest::evaluate(Evaluator &evaluator, ModuleDecl *mod) con
return false;

StringRef runtimePath = searchPathOpts.RuntimeResourcePath;
return (!runtimePath.empty() && prefixMatches(runtimePath, modulePath)) || (!sdkPath.empty() && prefixMatches(sdkPath, modulePath));
return (!runtimePath.empty() && pathStartsWith(runtimePath, modulePath)) ||
(!sdkPath.empty() && pathStartsWith(sdkPath, modulePath));
}
13 changes: 13 additions & 0 deletions lib/Basic/StringExtras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

Expand Down Expand Up @@ -1417,3 +1418,15 @@ void swift::writeEscaped(llvm::StringRef Str, llvm::raw_ostream &OS) {
}
}
}

bool swift::pathStartsWith(StringRef prefix, StringRef path) {
auto prefixIt = llvm::sys::path::begin(prefix),
prefixEnd = llvm::sys::path::end(prefix);
for (auto pathIt = llvm::sys::path::begin(path),
pathEnd = llvm::sys::path::end(path);
prefixIt != prefixEnd && pathIt != pathEnd; ++prefixIt, ++pathIt) {
if (*prefixIt != *pathIt)
return false;
}
return prefixIt == prefixEnd;
}
31 changes: 28 additions & 3 deletions lib/Frontend/ModuleInterfaceLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/FileSystem.h"
#include "swift/AST/Module.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Frontend/CachingUtils.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/ModuleInterfaceSupport.h"
Expand Down Expand Up @@ -233,6 +234,7 @@ struct ModuleRebuildInfo {
NotIgnored,
PublicFramework,
InterfacePreferred,
CompilerHostModule,
};
struct CandidateModule {
std::string path;
Expand Down Expand Up @@ -704,7 +706,28 @@ class ModuleInterfaceLoaderImpl {
bool isInResourceDir(StringRef path) {
StringRef resourceDir = ctx.SearchPathOpts.RuntimeResourcePath;
if (resourceDir.empty()) return false;
return path.startswith(resourceDir);
return pathStartsWith(resourceDir, path);
}

bool isInResourceHostDir(StringRef path) {
StringRef resourceDir = ctx.SearchPathOpts.RuntimeResourcePath;
if (resourceDir.empty()) return false;

SmallString<128> hostPath;
llvm::sys::path::append(hostPath,
resourceDir, "host");
return pathStartsWith(hostPath, path);
}

bool isInSystemFrameworks(StringRef path) {
StringRef sdkPath = ctx.SearchPathOpts.getSDKPath();
if (sdkPath.empty()) return false;

SmallString<128> publicFrameworksPath;
llvm::sys::path::append(publicFrameworksPath,
sdkPath, "System", "Library", "Frameworks");

return pathStartsWith(publicFrameworksPath, path);
}

std::pair<std::string, std::string> getCompiledModuleCandidates() {
Expand All @@ -719,10 +742,12 @@ class ModuleInterfaceLoaderImpl {
llvm::sys::path::append(publicFrameworksPath,
ctx.SearchPathOpts.getSDKPath(),
"System", "Library", "Frameworks");
if (!ctx.SearchPathOpts.getSDKPath().empty() &&
modulePath.startswith(publicFrameworksPath)) {
if (isInSystemFrameworks(modulePath)) {
shouldLoadAdjacentModule = false;
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::PublicFramework);
} else if (isInResourceHostDir(modulePath)) {
shouldLoadAdjacentModule = false;
rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::CompilerHostModule);
}

switch (loadMode) {
Expand Down
26 changes: 26 additions & 0 deletions test/ModuleInterface/ignore-adjacent-host-module.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/build/host)
// RUN: %empty-directory(%t/cache)
// RUN: split-file %s %t

/// Modules loaded from within lib/swift/host should also be rebuilt from
/// their interface (which actually means anything within resource-dir/host).

// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
// RUN: -swift-version 5 -enable-library-evolution \
// RUN: -parse-stdlib -module-cache-path %t/cache \
// RUN: -o %t/build/host -emit-module-interface-path %t/build/host/Lib.swiftinterface

// RUN: %target-swift-frontend -typecheck %t/Client.swift \
// RUN: -resource-dir %t/build -I %t/build/host \
// RUN: -parse-stdlib -module-cache-path %t/cache \
// RUN: -Rmodule-loading 2>&1 | %FileCheck %s

// CHECK: remark: loaded module 'Lib'; source: '{{.*}}{{/|\\}}host{{/|\\}}Lib.swiftinterface', loaded: '{{.*}}{{/|\\}}cache{{/|\\}}Lib-{{.*}}.swiftmodule'

//--- Lib.swift
public func foo() {}

//--- Client.swift
import Lib
foo()