Skip to content

Commit 683d469

Browse files
committed
Extends canImport to check for submodule availability
1 parent d1bb98b commit 683d469

24 files changed

+294
-51
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ class ASTContext final {
357357
DelayedPatternContexts;
358358

359359
/// Cache of module names that fail the 'canImport' test in this context.
360-
mutable llvm::SmallPtrSet<Identifier, 8> FailedModuleImportNames;
361-
360+
mutable llvm::StringSet<> FailedModuleImportNames;
361+
362362
/// Set if a `-module-alias` was passed. Used to store mapping between module aliases and
363363
/// their corresponding real names, and vice versa for a reverse lookup, which is needed to check
364364
/// if the module names appearing in source files are aliases or real names.
@@ -980,10 +980,10 @@ class ASTContext final {
980980
///
981981
/// Note that even if this check succeeds, errors may still occur if the
982982
/// module is loaded in full.
983-
bool canImportModuleImpl(ImportPath::Element ModulePath,
984-
llvm::VersionTuple version,
985-
bool underlyingVersion,
983+
bool canImportModuleImpl(ImportPath::Module ModulePath,
984+
llvm::VersionTuple version, bool underlyingVersion,
986985
bool updateFailingList) const;
986+
987987
public:
988988
namelookup::ImportCache &getImportCache() const;
989989

@@ -1012,10 +1012,10 @@ class ASTContext final {
10121012
///
10131013
/// Note that even if this check succeeds, errors may still occur if the
10141014
/// module is loaded in full.
1015-
bool canImportModule(ImportPath::Element ModulePath,
1015+
bool canImportModule(ImportPath::Module ModulePath,
10161016
llvm::VersionTuple version = llvm::VersionTuple(),
10171017
bool underlyingVersion = false);
1018-
bool canImportModule(ImportPath::Element ModulePath,
1018+
bool canImportModule(ImportPath::Module ModulePath,
10191019
llvm::VersionTuple version = llvm::VersionTuple(),
10201020
bool underlyingVersion = false) const;
10211021

include/swift/AST/Import.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ namespace detail {
225225
}
226226
}
227227

228+
/// Parses \p text into elements separated by \p separator, with identifiers
229+
/// from \p ctx starting at \p loc.
230+
///
231+
/// \warning This is not very robust; for instance, it doesn't check the
232+
/// validity of the identifiers.
233+
ImportPathBuilder(ASTContext &ctx, StringRef text, char separator,
234+
SourceLoc loc)
235+
: scratch() {
236+
while (!text.empty()) {
237+
StringRef next;
238+
std::tie(next, text) = text.split(separator);
239+
push_back({ImportPathBuilder_getIdentifierImpl(ctx, next), loc});
240+
loc = loc.getAdvancedLocOrInvalid(next.size() + 1);
241+
}
242+
}
243+
228244
void push_back(const ImportPathElement &elem) { scratch.push_back(elem); }
229245
void push_back(Identifier name, SourceLoc loc = SourceLoc()) {
230246
scratch.push_back({ name, loc });

include/swift/AST/ModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class ModuleLoader {
200200
///
201201
/// Note that even if this check succeeds, errors may still occur if the
202202
/// module is loaded in full.
203-
virtual bool canImportModule(ImportPath::Element named,
203+
virtual bool canImportModule(ImportPath::Module named,
204204
llvm::VersionTuple version,
205205
bool underlyingVersion) = 0;
206206

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ class ClangImporter final : public ClangModuleLoader {
192192
///
193193
/// Note that even if this check succeeds, errors may still occur if the
194194
/// module is loaded in full.
195-
virtual bool canImportModule(ImportPath::Element named, llvm::VersionTuple version,
195+
virtual bool canImportModule(ImportPath::Module named,
196+
llvm::VersionTuple version,
196197
bool underlyingVersion) override;
197198

198199
/// Import a module with the given module path.

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class ExplicitSwiftModuleLoader: public SerializedModuleLoaderBase {
151151
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
152152
bool skipBuildingInterface, bool IsFramework) override;
153153

154-
bool canImportModule(ImportPath::Element mID, llvm::VersionTuple version,
154+
bool canImportModule(ImportPath::Module named, llvm::VersionTuple version,
155155
bool underlyingVersion) override;
156156

157157
bool isCached(StringRef DepPath) override { return false; };

include/swift/Sema/SourceLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class SourceLoader : public ModuleLoader {
5757
///
5858
/// Note that even if this check succeeds, errors may still occur if the
5959
/// module is loaded in full.
60-
virtual bool canImportModule(ImportPath::Element named,
60+
virtual bool canImportModule(ImportPath::Module named,
6161
llvm::VersionTuple version,
6262
bool underlyingVersion) override;
6363

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
168168
///
169169
/// Note that even if this check succeeds, errors may still occur if the
170170
/// module is loaded in full.
171-
virtual bool canImportModule(ImportPath::Element named,
171+
virtual bool canImportModule(ImportPath::Module named,
172172
llvm::VersionTuple version,
173173
bool underlyingVersion) override;
174174

@@ -287,7 +287,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
287287
public:
288288
virtual ~MemoryBufferSerializedModuleLoader();
289289

290-
bool canImportModule(ImportPath::Element named, llvm::VersionTuple version,
290+
bool canImportModule(ImportPath::Module named, llvm::VersionTuple version,
291291
bool underlyingVersion) override;
292292
ModuleDecl *
293293
loadModule(SourceLoc importLoc,

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,17 +2168,21 @@ bool ASTContext::shouldPerformTypoCorrection() {
21682168
return NumTypoCorrections <= LangOpts.TypoCorrectionLimit;
21692169
}
21702170

2171-
bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName,
2171+
bool ASTContext::canImportModuleImpl(ImportPath::Module ModuleName,
21722172
llvm::VersionTuple version,
21732173
bool underlyingVersion,
21742174
bool updateFailingList) const {
2175+
SmallString<64> FullModuleName;
2176+
ModuleName.getString(FullModuleName);
2177+
auto ModuleNameStr = FullModuleName.str();
2178+
21752179
// If we've failed loading this module before, don't look for it again.
2176-
if (FailedModuleImportNames.count(ModuleName.Item))
2180+
if (FailedModuleImportNames.count(ModuleNameStr))
21772181
return false;
21782182
// If no specific version, the module is importable if it has already been imported.
21792183
if (version.empty()) {
21802184
// If this module has already been successfully imported, it is importable.
2181-
if (getLoadedModule(ImportPath::Module::Builder(ModuleName).get()) != nullptr)
2185+
if (getLoadedModule(ModuleName) != nullptr)
21822186
return true;
21832187
}
21842188
// Otherwise, ask the module loaders.
@@ -2188,18 +2192,18 @@ bool ASTContext::canImportModuleImpl(ImportPath::Element ModuleName,
21882192
}
21892193
}
21902194
if (updateFailingList && version.empty()) {
2191-
FailedModuleImportNames.insert(ModuleName.Item);
2195+
FailedModuleImportNames.insert(ModuleNameStr);
21922196
}
21932197
return false;
21942198
}
21952199

2196-
bool ASTContext::canImportModule(ImportPath::Element ModuleName,
2200+
bool ASTContext::canImportModule(ImportPath::Module ModuleName,
21972201
llvm::VersionTuple version,
21982202
bool underlyingVersion) {
21992203
return canImportModuleImpl(ModuleName, version, underlyingVersion, true);
22002204
}
22012205

2202-
bool ASTContext::canImportModule(ImportPath::Element ModuleName,
2206+
bool ASTContext::canImportModule(ImportPath::Module ModuleName,
22032207
llvm::VersionTuple version,
22042208
bool underlyingVersion) const {
22052209
return canImportModuleImpl(ModuleName, version, underlyingVersion, false);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,14 +1808,14 @@ static std::string getScalaNodeText(llvm::yaml::Node *N) {
18081808
return cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer).str();
18091809
}
18101810

1811-
bool ClangImporter::canImportModule(ImportPath::Element moduleID,
1811+
bool ClangImporter::canImportModule(ImportPath::Module modulePath,
18121812
llvm::VersionTuple version,
18131813
bool underlyingVersion) {
18141814
// Look up the top-level module to see if it exists.
1815-
// FIXME: This only works with top-level modules.
18161815
auto &clangHeaderSearch = Impl.getClangPreprocessor().getHeaderSearchInfo();
1816+
auto topModule = modulePath.front();
18171817
clang::Module *clangModule = clangHeaderSearch.lookupModule(
1818-
moduleID.Item.str(), /*ImportLoc=*/clang::SourceLocation(),
1818+
topModule.Item.str(), /*ImportLoc=*/clang::SourceLocation(),
18191819
/*AllowSearch=*/true, /*AllowExtraModuleMapSearch=*/true);
18201820
if (!clangModule) {
18211821
return false;
@@ -1825,10 +1825,34 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18251825
clang::Module::UnresolvedHeaderDirective mh;
18261826
clang::Module *m;
18271827
auto &ctx = Impl.getClangASTContext();
1828-
auto available = clangModule->isAvailable(ctx.getLangOpts(), getTargetInfo(),
1829-
r, mh, m);
1828+
auto &lo = ctx.getLangOpts();
1829+
auto &ti = getTargetInfo();
1830+
1831+
auto available = clangModule->isAvailable(lo, ti, r, mh, m);
18301832
if (!available)
18311833
return false;
1834+
1835+
if (modulePath.hasSubmodule()) {
1836+
for (auto &component : modulePath.getSubmodulePath()) {
1837+
clangModule = clangModule->findSubmodule(component.Item.str());
1838+
1839+
// Special case: a submodule named "Foo.Private" can be moved to a
1840+
// top-level module named "Foo_Private". Clang has special support for
1841+
// this.
1842+
if (!clangModule && component.Item.str() == "Private" &&
1843+
(&component) == (&modulePath.getRaw()[1])) {
1844+
clangModule = clangHeaderSearch.lookupModule(
1845+
(topModule.Item.str() + "_Private").str(),
1846+
/*ImportLoc=*/clang::SourceLocation(),
1847+
/*AllowSearch=*/true,
1848+
/*AllowExtraModuleMapSearch=*/true);
1849+
}
1850+
if (!clangModule || !clangModule->isAvailable(lo, ti, r, mh, m)) {
1851+
return false;
1852+
}
1853+
}
1854+
}
1855+
18321856
if (version.empty())
18331857
return true;
18341858
assert(available);
@@ -1838,11 +1862,11 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18381862
.getFilename(clangModule->DefinitionLoc);
18391863
// Look for the .tbd file inside .framework dir to get the project version
18401864
// number.
1841-
std::string fwName = (llvm::Twine(moduleID.Item.str()) + ".framework").str();
1865+
std::string fwName = (llvm::Twine(topModule.Item.str()) + ".framework").str();
18421866
auto pos = path.find(fwName);
18431867
while (pos != StringRef::npos) {
18441868
llvm::SmallString<256> buffer(path.substr(0, pos + fwName.size()));
1845-
llvm::sys::path::append(buffer, llvm::Twine(moduleID.Item.str()) + ".tbd");
1869+
llvm::sys::path::append(buffer, llvm::Twine(topModule.Item.str()) + ".tbd");
18461870
auto tbdPath = buffer.str();
18471871
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> tbdBufOrErr =
18481872
llvm::MemoryBuffer::getFile(tbdPath);
@@ -1877,8 +1901,8 @@ bool ClangImporter::canImportModule(ImportPath::Element moduleID,
18771901
}
18781902
// Diagnose unable to checking the current version.
18791903
if (currentVersion.empty()) {
1880-
Impl.diagnose(moduleID.Loc, diag::cannot_find_project_version, "Clang",
1881-
moduleID.Item.str());
1904+
Impl.diagnose(topModule.Loc, diag::cannot_find_project_version, "Clang",
1905+
topModule.Item.str());
18821906
return true;
18831907
}
18841908
assert(!currentVersion.empty());

lib/ClangImporter/ImportType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2726,7 +2726,9 @@ ModuleDecl *ClangImporter::Implementation::tryLoadFoundationModule() {
27262726
}
27272727

27282728
bool ClangImporter::Implementation::canImportFoundationModule() {
2729-
return SwiftContext.canImportModule({SwiftContext.Id_Foundation, SourceLoc()});
2729+
ImportPath::Module::Builder builder(SwiftContext.Id_Foundation);
2730+
auto modulePath = builder.get();
2731+
return SwiftContext.canImportModule(modulePath);
27302732
}
27312733

27322734
Type ClangImporter::Implementation::getNamedSwiftType(ModuleDecl *module,

0 commit comments

Comments
 (0)