Skip to content

Frontend: Refactor import collection for module interface printing #76783

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 3 commits into from
Oct 1, 2024
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
11 changes: 4 additions & 7 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,16 +934,13 @@ class ModuleDecl
enum class ImportFilterKind {
/// Include imports declared with `@_exported`.
Exported = 1 << 0,
/// Include "regular" imports with an access-level of `public`.
/// Include "regular" imports with an effective access level of `public`.
Default = 1 << 1,
/// Include imports declared with `@_implementationOnly`.
ImplementationOnly = 1 << 2,
/// Include imports declared with `package import`.
/// Include imports declared with an access level of `package`.
PackageOnly = 1 << 3,
/// Include imports marked `internal` or lower. These differs form
/// implementation-only imports by stricter type-checking and loading
/// policies. At this moment, we can group them under the same category
/// as they have the same loading behavior.
/// Include imports with an effective access level of `internal` or lower.
InternalOrBelow = 1 << 4,
/// Include imports declared with `@_spiOnly`.
SPIOnly = 1 << 5,
Expand Down Expand Up @@ -983,7 +980,7 @@ class ModuleDecl
/// \p filter controls whether public, private, or any imports are included
/// in this list.
void getImportedModules(SmallVectorImpl<ImportedModule> &imports,
ImportFilter filter = ImportFilterKind::Exported) const;
ImportFilter filter) const;

/// Looks up which external macros are defined by this file.
void getExternalMacros(SmallVectorImpl<ExternalMacroPlugin> &macros) const;
Expand Down
45 changes: 18 additions & 27 deletions lib/Frontend/ModuleInterfaceSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,15 @@ static void printImports(raw_ostream &out,
ModuleDecl::ImportFilterKind::Default,
ModuleDecl::ImportFilterKind::ShadowedByCrossImportOverlay};

using ImportSet = llvm::SmallSet<ImportedModule, 8, ImportedModule::Order>;
auto getImports = [M](ModuleDecl::ImportFilter filter) -> ImportSet {
SmallVector<ImportedModule, 8> matchingImports;
M->getImportedModules(matchingImports, filter);
ImportSet importSet;
importSet.insert(matchingImports.begin(), matchingImports.end());
return importSet;
};

// With -experimental-spi-imports:
// When printing the private or package swiftinterface file, print implementation-only
// imports only if they are also SPI. First, list all implementation-only imports and
Expand All @@ -282,10 +291,7 @@ static void printImports(raw_ostream &out,
ModuleDecl::ImportFilterKind::ImplementationOnly);

// Only consider modules imported consistently as implementation-only.
M->getImportedModules(allImports,
allImportFilter);
llvm::SmallSet<ImportedModule, 8, ImportedModule::Order> allImportSet;
allImportSet.insert(allImports.begin(), allImports.end());
ImportSet allImportSet = getImports(allImportFilter);

for (auto import: ioiImports)
if (allImportSet.count(import) == 0)
Expand All @@ -295,16 +301,13 @@ static void printImports(raw_ostream &out,
}

/// Collect @_spiOnly imports that are not imported elsewhere publicly.
llvm::SmallSet<ImportedModule, 4, ImportedModule::Order> spiOnlyImportSet;
ImportSet spiOnlyImportSet;
if (!Opts.printPublicInterface()) {
SmallVector<ImportedModule, 4> spiOnlyImports, otherImports;
M->getImportedModules(spiOnlyImports,
ModuleDecl::ImportFilterKind::SPIOnly);

M->getImportedModules(otherImports,
allImportFilter);
llvm::SmallSet<ImportedModule, 8, ImportedModule::Order> otherImportsSet;
otherImportsSet.insert(otherImports.begin(), otherImports.end());
ImportSet otherImportsSet = getImports(allImportFilter);

// Rule out inconsistent imports.
for (auto import: spiOnlyImports)
Expand All @@ -316,25 +319,19 @@ static void printImports(raw_ostream &out,

// Collect the public imports as a subset so that we can mark them with
// '@_exported'.
SmallVector<ImportedModule, 8> exportedImports;
M->getImportedModules(exportedImports, ModuleDecl::ImportFilterKind::Exported);
llvm::SmallSet<ImportedModule, 8, ImportedModule::Order> exportedImportSet;
exportedImportSet.insert(exportedImports.begin(), exportedImports.end());
ImportSet exportedImportSet =
getImports(ModuleDecl::ImportFilterKind::Exported);

// All of the above are considered `public` including `@_spiOnly public import`
// and `@_spi(name) public import`, and should override `package import`.
// Track the `public` imports here to determine whether to override.
llvm::SmallSet<ImportedModule, 8, ImportedModule::Order> publicImportSet;
SmallVector<ImportedModule, 8> publicImports;
M->getImportedModules(publicImports, allImportFilter);
publicImportSet.insert(publicImports.begin(), publicImports.end());
ImportSet publicImportSet = getImports(allImportFilter);

// Used to determine whether `package import` should be overriden below.
llvm::SmallSet<ImportedModule, 8, ImportedModule::Order> packageOnlyImportSet;
ImportSet packageOnlyImportSet;
if (Opts.printPackageInterface()) {
SmallVector<ImportedModule, 8> packageOnlyImports;
M->getImportedModules(packageOnlyImports, ModuleDecl::ImportFilterKind::PackageOnly);
packageOnlyImportSet.insert(packageOnlyImports.begin(), packageOnlyImports.end());
packageOnlyImportSet =
getImports(ModuleDecl::ImportFilterKind::PackageOnly);
allImportFilter |= ModuleDecl::ImportFilterKind::PackageOnly;
}

Expand Down Expand Up @@ -382,12 +379,6 @@ static void printImports(raw_ostream &out,

if (!Opts.printPublicInterface()) {
// An import visible in the private or package swiftinterface only.
//
// In the long term, we want to print this attribute for consistency and
// to enforce exportability analysis of generated code.
// For now, not printing the attribute allows us to have backwards
// compatible swiftinterfaces and we can live without
// checking the generate code for a while.
if (spiOnlyImportSet.count(import))
out << "@_spiOnly ";

Expand Down
2 changes: 1 addition & 1 deletion lib/IDE/ImportDepth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ImportDepth::ImportDepth(ASTContext &context,

// Add imports to the worklist.
SmallVector<ImportedModule, 16> imports;
module->getImportedModules(imports);
module->getImportedModules(imports, ModuleDecl::ImportFilterKind::Exported);
for (auto &import : imports) {
uint8_t next = std::max(depth, uint8_t(depth + 1)); // unsigned wrap

Expand Down
6 changes: 1 addition & 5 deletions lib/Index/Index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2091,12 +2091,8 @@ void IndexSwiftASTWalker::collectRecursiveModuleImports(
return;
}

ModuleDecl::ImportFilter ImportFilter;
ImportFilter |= ModuleDecl::ImportFilterKind::Exported;
ImportFilter |= ModuleDecl::ImportFilterKind::Default;
// FIXME: ImportFilterKind::ShadowedByCrossImportOverlay?
SmallVector<ImportedModule, 8> Imports;
TopMod.getImportedModules(Imports);
TopMod.getImportedModules(Imports, ModuleDecl::ImportFilterKind::Exported);

for (auto Import : Imports) {
collectRecursiveModuleImports(*Import.importedModule, Visited);
Expand Down