[ModuleInterface] Hide non-public imports from a resilient module

When using access level on imports, consider non-public imports to be
implementation details not exposed to clients. As such, a client loading
a library doesn't need to load non-public transitive dependencies.

This behave like `@_implementationOnly imports` at a module-wide level,
but it is restricted to resilient modules only. An import with any
access-level in a non-resilient module remains visible to transitive
clients.
This commit is contained in:
Alexis Laferrière
2023-02-24 17:40:57 -08:00
parent 78749d8d00
commit 94aeb8c0ff
4 changed files with 158 additions and 2 deletions

View File

@@ -1887,11 +1887,14 @@ SourceFile::getImportedModules(SmallVectorImpl<ImportedModule> &modules,
if (!Imports)
return;
bool moduleIsResilient = getParentModule()->getResilienceStrategy() ==
ResilienceStrategy::Resilient;
for (auto desc : *Imports) {
ModuleDecl::ImportFilter requiredFilter;
if (desc.options.contains(ImportFlags::Exported))
requiredFilter |= ModuleDecl::ImportFilterKind::Exported;
else if (desc.options.contains(ImportFlags::ImplementationOnly))
else if (desc.options.contains(ImportFlags::ImplementationOnly) ||
(desc.accessLevel <= AccessLevel::Package && moduleIsResilient))
requiredFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
else if (desc.options.contains(ImportFlags::SPIOnly))
requiredFilter |= ModuleDecl::ImportFilterKind::SPIOnly;