Skip to content
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
44 changes: 32 additions & 12 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,26 +209,46 @@ class ModuleDecl : public DeclContext, public TypeDecl {

public:
typedef ArrayRef<Located<Identifier>> AccessPathTy;
typedef std::pair<ModuleDecl::AccessPathTy, ModuleDecl*> ImportedModule;

/// Convenience struct to keep track of a module along with its access path.
struct ImportedModule {
/// The access path from an import: `import Foo.Bar` -> `Foo.Bar`.
ModuleDecl::AccessPathTy accessPath;
/// The actual module corresponding to the import.
///
/// Invariant: The pointer is non-null.
ModuleDecl *importedModule;

ImportedModule(ModuleDecl::AccessPathTy accessPath,
ModuleDecl *importedModule)
: accessPath(accessPath), importedModule(importedModule) {
assert(this->importedModule);
}

bool operator==(const ModuleDecl::ImportedModule &other) const {
return (this->importedModule == other.importedModule) &&
(this->accessPath == other.accessPath);
}
};

static bool matchesAccessPath(AccessPathTy AccessPath, DeclName Name) {
assert(AccessPath.size() <= 1 && "can only refer to top-level decls");

return AccessPath.empty()
|| DeclName(AccessPath.front().Item).matchesRef(Name);
}

/// Arbitrarily orders ImportedModule records, for inclusion in sets and such.
class OrderImportedModules {
public:
bool operator()(const ImportedModule &lhs,
const ImportedModule &rhs) const {
if (lhs.second != rhs.second)
return std::less<const ModuleDecl *>()(lhs.second, rhs.second);
if (lhs.first.data() != rhs.first.data())
return std::less<AccessPathTy::iterator>()(lhs.first.begin(),
rhs.first.begin());
return lhs.first.size() < rhs.first.size();
if (lhs.importedModule != rhs.importedModule)
return std::less<const ModuleDecl *>()(lhs.importedModule,
rhs.importedModule);
if (lhs.accessPath.data() != rhs.accessPath.data())
return std::less<AccessPathTy::iterator>()(lhs.accessPath.begin(),
rhs.accessPath.begin());
return lhs.accessPath.size() < rhs.accessPath.size();
}
};

Expand Down Expand Up @@ -860,14 +880,14 @@ namespace llvm {
}

static unsigned getHashValue(const ModuleDecl::ImportedModule &val) {
auto pair = std::make_pair(val.first.size(), val.second);
auto pair = std::make_pair(val.accessPath.size(), val.importedModule);
return llvm::DenseMapInfo<decltype(pair)>::getHashValue(pair);
}

static bool isEqual(const ModuleDecl::ImportedModule &lhs,
const ModuleDecl::ImportedModule &rhs) {
return lhs.second == rhs.second &&
ModuleDecl::isSameAccessPath(lhs.first, rhs.first);
return lhs.importedModule == rhs.importedModule &&
ModuleDecl::isSameAccessPath(lhs.accessPath, rhs.accessPath);
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/AutoDiff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ bool swift::isDifferentiableProgrammingEnabled(SourceFile &SF) {
// the given source file.
bool importsDifferentiationModule = false;
for (auto import : namelookup::getAllImports(&SF)) {
if (import.second->getName() == ctx.Id_Differentiation) {
if (import.importedModule->getName() == ctx.Id_Differentiation) {
importsDifferentiationModule = true;
break;
}
Expand Down
42 changes: 23 additions & 19 deletions lib/AST/ImportCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,26 @@ void ImportSet::Profile(
ArrayRef<ModuleDecl::ImportedModule> topLevelImports) {
ID.AddInteger(topLevelImports.size());
for (auto import : topLevelImports) {
ID.AddInteger(import.first.size());
for (auto accessPathElt : import.first) {
ID.AddInteger(import.accessPath.size());
for (auto accessPathElt : import.accessPath) {
ID.AddPointer(accessPathElt.Item.getAsOpaquePointer());
}
ID.AddPointer(import.second);
ID.AddPointer(import.importedModule);
}
}

static void collectExports(ModuleDecl::ImportedModule next,
SmallVectorImpl<ModuleDecl::ImportedModule> &stack) {
SmallVector<ModuleDecl::ImportedModule, 4> exports;
next.second->getImportedModulesForLookup(exports);
next.importedModule->getImportedModulesForLookup(exports);
for (auto exported : exports) {
if (next.first.empty())
if (next.accessPath.empty())
stack.push_back(exported);
else if (exported.first.empty()) {
exported.first = next.first;
else if (exported.accessPath.empty()) {
exported.accessPath = next.accessPath;
stack.push_back(exported);
} else if (ModuleDecl::isSameAccessPath(next.first, exported.first)) {
} else if (ModuleDecl::isSameAccessPath(next.accessPath,
exported.accessPath)) {
stack.push_back(exported);
}
}
Expand All @@ -97,7 +98,7 @@ ImportCache::getImportSet(ASTContext &ctx,
continue;

topLevelImports.push_back(next);
if (next.second == headerImportModule)
if (next.importedModule == headerImportModule)
hasHeaderImportModule = true;
}

Expand Down Expand Up @@ -127,7 +128,7 @@ ImportCache::getImportSet(ASTContext &ctx,
continue;

transitiveImports.push_back(next);
if (next.second == headerImportModule)
if (next.importedModule == headerImportModule)
hasHeaderImportModule = true;

collectExports(next, stack);
Expand Down Expand Up @@ -173,7 +174,9 @@ ImportSet &ImportCache::getImportSet(const DeclContext *dc) {
ctx.Stats->getFrontendCounters().ImportSetCacheMiss++;

SmallVector<ModuleDecl::ImportedModule, 4> imports;
imports.emplace_back(ModuleDecl::AccessPathTy(), mod);

imports.emplace_back(
ModuleDecl::ImportedModule{ModuleDecl::AccessPathTy(), mod});

if (file) {
ModuleDecl::ImportFilter importFilter;
Expand Down Expand Up @@ -220,10 +223,10 @@ ImportCache::getAllVisibleAccessPaths(const ModuleDecl *mod,
SmallVector<ModuleDecl::AccessPathTy, 1> accessPaths;
for (auto next : getImportSet(dc).getAllImports()) {
// If we found 'mod', record the access path.
if (next.second == mod) {
if (next.importedModule == mod) {
// Make sure the list of access paths is unique.
if (!llvm::is_contained(accessPaths, next.first))
accessPaths.push_back(next.first);
if (!llvm::is_contained(accessPaths, next.accessPath))
accessPaths.push_back(next.accessPath);
}
}

Expand Down Expand Up @@ -258,7 +261,8 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod,
SmallVector<ModuleDecl::ImportedModule, 4> stack;
llvm::SmallDenseSet<ModuleDecl::ImportedModule, 32> visited;

stack.emplace_back(ModuleDecl::AccessPathTy(), currentMod);
stack.emplace_back(
ModuleDecl::ImportedModule{ModuleDecl::AccessPathTy(), currentMod});

if (auto *file = dyn_cast<FileUnit>(dc)) {
ModuleDecl::ImportFilter importFilter;
Expand All @@ -278,15 +282,15 @@ ImportCache::getAllAccessPathsNotShadowedBy(const ModuleDecl *mod,
continue;

// Don't visit the 'other' module's re-exports.
if (next.second == other)
if (next.importedModule == other)
continue;

// If we found 'mod' via some access path, remember the access
// path.
if (next.second == mod) {
if (next.importedModule == mod) {
// Make sure the list of access paths is unique.
if (!llvm::is_contained(accessPaths, next.first))
accessPaths.push_back(next.first);
if (!llvm::is_contained(accessPaths, next.accessPath))
accessPaths.push_back(next.accessPath);
}

collectExports(next, stack);
Expand Down
62 changes: 31 additions & 31 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,17 +1215,16 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
ImportedOperatorsMap<OP_DECL> importedOperators;
for (auto &imported : SourceFile::Impl::getImportsForSourceFile(SF)) {
// Protect against source files that contrive to import their own modules.
if (imported.module.second == ownModule)
if (imported.module.importedModule == ownModule)
continue;

bool isExported =
imported.importOptions.contains(SourceFile::ImportFlags::Exported);
if (!includePrivate && !isExported)
continue;

Optional<OP_DECL *> maybeOp =
lookupOperatorDeclForName<OP_DECL>(imported.module.second, Loc, Name,
isCascading);
Optional<OP_DECL *> maybeOp = lookupOperatorDeclForName<OP_DECL>(
imported.module.importedModule, Loc, Name, isCascading);
if (!maybeOp)
return None;

Expand Down Expand Up @@ -1418,7 +1417,7 @@ SourceFile::getImportedModules(SmallVectorImpl<ModuleDecl::ImportedModule> &modu
else
requiredFilter |= ModuleDecl::ImportFilterKind::Private;

if (!separatelyImportedOverlays.lookup(desc.module.second).empty())
if (!separatelyImportedOverlays.lookup(desc.module.importedModule).empty())
requiredFilter |= ModuleDecl::ImportFilterKind::ShadowedBySeparateOverlay;

if (filter.contains(requiredFilter))
Expand Down Expand Up @@ -1513,26 +1512,26 @@ ModuleDecl::removeDuplicateImports(SmallVectorImpl<ImportedModule> &imports) {
std::sort(imports.begin(), imports.end(),
[](const ImportedModule &lhs, const ImportedModule &rhs) -> bool {
// Arbitrarily sort by name to get a deterministic order.
if (lhs.second != rhs.second) {
if (lhs.importedModule != rhs.importedModule) {
return std::lexicographical_compare(
lhs.second->getReverseFullModuleName(), {},
rhs.second->getReverseFullModuleName(), {});
lhs.importedModule->getReverseFullModuleName(), {},
rhs.importedModule->getReverseFullModuleName(), {});
}
using AccessPathElem = Located<Identifier>;
return std::lexicographical_compare(lhs.first.begin(), lhs.first.end(),
rhs.first.begin(), rhs.first.end(),
[](const AccessPathElem &lElem,
const AccessPathElem &rElem) {
return lElem.Item.str() < rElem.Item.str();
});
});
auto last = std::unique(imports.begin(), imports.end(),
[](const ImportedModule &lhs,
const ImportedModule &rhs) -> bool {
if (lhs.second != rhs.second)
return false;
return ModuleDecl::isSameAccessPath(lhs.first, rhs.first);
return std::lexicographical_compare(
lhs.accessPath.begin(), lhs.accessPath.end(), rhs.accessPath.begin(),
rhs.accessPath.end(),
[](const AccessPathElem &lElem, const AccessPathElem &rElem) {
return lElem.Item.str() < rElem.Item.str();
});
});
auto last = std::unique(
imports.begin(), imports.end(),
[](const ImportedModule &lhs, const ImportedModule &rhs) -> bool {
if (lhs.importedModule != rhs.importedModule)
return false;
return ModuleDecl::isSameAccessPath(lhs.accessPath, rhs.accessPath);
});
imports.erase(last, imports.end());
}

Expand Down Expand Up @@ -1693,11 +1692,12 @@ SourceFile::collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const
topLevel->getImportedModules(stack, topLevelFilter);

// Make sure the top-level module is first; we want pre-order-ish traversal.
stack.emplace_back(ModuleDecl::AccessPathTy(),
const_cast<ModuleDecl *>(topLevel));
auto topLevelModule =
ModuleDecl::ImportedModule{ModuleDecl::AccessPathTy(), topLevel};
stack.emplace_back(topLevelModule);

while (!stack.empty()) {
auto next = stack.pop_back_val().second;
auto next = stack.pop_back_val().importedModule;

if (!visited.insert(next).second)
continue;
Expand Down Expand Up @@ -1905,7 +1905,7 @@ ModuleDecl::getDeclaringModuleAndBystander() {

getImportedModules(imported, ModuleDecl::ImportFilterKind::Public);
while (!imported.empty()) {
ModuleDecl *importedModule = std::get<1>(imported.back());
ModuleDecl *importedModule = imported.back().importedModule;
imported.pop_back();
if (!seen.insert(importedModule).second)
continue;
Expand Down Expand Up @@ -2124,15 +2124,15 @@ bool SourceFile::hasTestableOrPrivateImport(
Imports->begin(), Imports->end(),
[module, queryKind](ImportedModuleDesc desc) -> bool {
if (queryKind == ImportQueryKind::TestableAndPrivate)
return desc.module.second == module &&
return desc.module.importedModule == module &&
(desc.importOptions.contains(ImportFlags::PrivateImport) ||
desc.importOptions.contains(ImportFlags::Testable));
else if (queryKind == ImportQueryKind::TestableOnly)
return desc.module.second == module &&
return desc.module.importedModule == module &&
desc.importOptions.contains(ImportFlags::Testable);
else {
assert(queryKind == ImportQueryKind::PrivateOnly);
return desc.module.second == module &&
return desc.module.importedModule == module &&
desc.importOptions.contains(ImportFlags::PrivateImport);
}
});
Expand Down Expand Up @@ -2165,7 +2165,7 @@ bool SourceFile::hasTestableOrPrivateImport(

return std::any_of(Imports->begin(), Imports->end(),
[module, filename](ImportedModuleDesc desc) -> bool {
return desc.module.second == module &&
return desc.module.importedModule == module &&
desc.importOptions.contains(
ImportFlags::PrivateImport) &&
desc.filename == filename;
Expand All @@ -2188,7 +2188,7 @@ bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const {

// If the module is imported this way, it's not imported
// implementation-only.
if (imports.isImportedBy(module, desc.module.second))
if (imports.isImportedBy(module, desc.module.importedModule))
return false;
}

Expand All @@ -2200,7 +2200,7 @@ void SourceFile::lookupImportedSPIGroups(const ModuleDecl *importedModule,
SmallVectorImpl<Identifier> &spiGroups) const {
for (auto &import : *Imports) {
if (import.importOptions.contains(ImportFlags::SPIAccessControl) &&
importedModule == std::get<ModuleDecl*>(import.module)) {
importedModule == import.module.importedModule) {
auto importedSpis = import.spiGroups;
spiGroups.append(importedSpis.begin(), importedSpis.end());
}
Expand Down
18 changes: 10 additions & 8 deletions lib/AST/ModuleNameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,14 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(

auto visitImport = [&](ModuleDecl::ImportedModule import,
const DeclContext *moduleScopeContext) {
if (import.first.empty())
import.first = accessPath;
if (import.accessPath.empty())
import.accessPath = accessPath;
else if (!accessPath.empty() &&
!ModuleDecl::isSameAccessPath(import.first, accessPath))
!ModuleDecl::isSameAccessPath(import.accessPath, accessPath))
return;

getDerived()->doLocalLookup(import.second, import.first, decls);
getDerived()->doLocalLookup(import.importedModule, import.accessPath,
decls);
updateNewDecls(moduleScopeContext);
};

Expand All @@ -201,7 +202,8 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
if (auto *loader = ctx.getClangModuleLoader()) {
headerImportModule = loader->getImportedHeaderModule();
if (headerImportModule) {
ModuleDecl::ImportedModule import({}, headerImportModule);
ModuleDecl::ImportedModule import{ModuleDecl::AccessPathTy(),
headerImportModule};
visitImport(import, nullptr);
}
}
Expand All @@ -210,19 +212,19 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
for (auto import : imports.getTopLevelImports()) {
// A module appears in its own top-level import list; since we checked
// it already, skip it.
if (import.second == module)
if (import.importedModule == module)
continue;

// Skip the special import set module; we've already visited it.
if (import.second == headerImportModule)
if (import.importedModule == headerImportModule)
continue;

visitImport(import, moduleScopeContext);
}

for (auto import : imports.getTransitiveImports()) {
// Skip the special import set module; we've already visited it.
if (import.second == headerImportModule)
if (import.importedModule == headerImportModule)
continue;

visitImport(import, nullptr);
Expand Down
Loading