Skip to content
Open
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
20 changes: 7 additions & 13 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2990,10 +2990,10 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
assert(targetModule != getParentModule() &&
"getImportAccessLevel doesn't support checking for a self-import");

/// Order of relevancy of `import` to reach `targetModule` assuming the same
/// visibility level. Lower is better/more authoritative.
/// Order of relevancy of `import` to reach `targetModule`.
/// Lower is better/more authoritative.
auto rateImport = [&](const ImportAccessLevel import) -> int {
auto importedModule = import->module.importedModule->getTopLevelModule();
auto importedModule = import->module.importedModule;

// Prioritize public names:
if (targetModule->getExportAsName() == importedModule->getBaseIdentifier())
Expand All @@ -3008,14 +3008,9 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
if (targetModule == importedModule->getUnderlyingModuleIfOverlay())
return 3;

// Any import in the sources:
if (import->importLoc.isValid()) {
// Prefer clang submodules to their top level modules:
if (import->module.importedModule != importedModule)
return 4;

return 5;
}
// Any import in the sources.
if (import->importLoc.isValid())
return 4;

return 10;
};
Expand All @@ -3025,12 +3020,11 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
auto &imports = getASTContext().getImportCache();
ImportAccessLevel restrictiveImport = std::nullopt;
for (auto &import : *Imports) {
auto importedModule = import.module.importedModule->getTopLevelModule();
if ((!restrictiveImport.has_value() ||
import.accessLevel > restrictiveImport->accessLevel ||
(import.accessLevel == restrictiveImport->accessLevel &&
rateImport(import) < rateImport(restrictiveImport))) &&
imports.isImportedBy(targetModule, importedModule)) {
imports.isImportedBy(targetModule, import.module.importedModule)) {
restrictiveImport = import;
}
}
Expand Down
38 changes: 12 additions & 26 deletions lib/Sema/ImportResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,6 @@ class ImportResolver final : public DeclVisitor<ImportResolver> {
/// The list of fully bound imports.
SmallVector<AttributedImport<ImportedModule>, 16> boundImports;

/// Set of imported top-level clang modules. We normally don't expect
/// duplicated imports, but importing multiple submodules of the same clang
/// TLM would cause the same TLM to be imported once per submodule.
SmallPtrSet<const ModuleDecl*, 16> seenClangTLMs;

/// All imported modules which should be considered when cross-importing.
/// This is basically the transitive import graph, but with only top-level
/// modules and without reexports from Objective-C modules.
Expand Down Expand Up @@ -347,11 +342,6 @@ void swift::performImportResolutionForClangMacroBuffer(
SF.ASTStage = SourceFile::ImportsResolved;
}

static bool isSubmodule(const ModuleDecl* M) {
auto clangMod = M->findUnderlyingClangModule();
return clangMod && clangMod->Parent;
}

//===----------------------------------------------------------------------===//
// MARK: Import handling generally
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -419,23 +409,14 @@ void ImportResolver::bindImport(UnboundImport &&I) {

I.validateOptions(topLevelModule, SF);

auto alreadyImportedTLM = [ID,this](const ModuleDecl *MD) {
ASSERT(!isSubmodule(MD));
// Scoped imports don't import all symbols from the module, so a scoped
// import does not count the module as imported
if (ID && isScopedImportKind(ID.get()->getImportKind()))
return false;
return !seenClangTLMs.insert(MD).second;
};
if (!M->isNonSwiftModule() || topLevelModule != M || !alreadyImportedTLM(M)) {
if (topLevelModule && topLevelModule != M) {
// If we have distinct submodule and top-level module, add both.
addImport(I, M);
addImport(I, topLevelModule.get());
}
else {
// Add only the import itself.
addImport(I, M);
if (topLevelModule && topLevelModule != M &&
!alreadyImportedTLM(topLevelModule.get())) {
// If we have distinct submodule and top-level module, add both.
// Importing the submodule ensures that it gets loaded, but the decls
// are imported to the TLM, so import that for visibility.
addImport(I, topLevelModule.get());
}
}

crossImport(M, I);
Expand Down Expand Up @@ -1655,6 +1636,11 @@ void ImportResolver::findCrossImports(
}
}

static bool isSubmodule(ModuleDecl* M) {
auto clangMod = M->findUnderlyingClangModule();
return clangMod && clangMod->Parent;
}

void ImportResolver::addCrossImportableModules(
AttributedImport<ImportedModule> importDesc) {
// FIXME: namelookup::getAllImports() doesn't quite do what we need (mainly
Expand Down
8 changes: 3 additions & 5 deletions lib/Sema/ResilienceDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
ModuleDecl *importedVia = attributedImport.module.importedModule,
*sourceModule = D->getModuleContext();
ctx.Diags.diagnose(loc, diag::module_api_import_aliases, D, importedVia,
sourceModule,
importedVia->getTopLevelModule() == sourceModule);
sourceModule, importedVia == sourceModule);
});

auto ignoredDowngradeToWarning = DowngradeToWarning::No;
Expand Down Expand Up @@ -290,8 +289,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
ModuleDecl *importedVia = attributedImport.module.importedModule,
*sourceModule = D->getModuleContext();
ctx.Diags.diagnose(loc, diag::module_api_import, D, importedVia,
sourceModule,
importedVia->getTopLevelModule() == sourceModule,
sourceModule, importedVia == sourceModule,
/*isImplicit*/ false);
}
});
Expand Down Expand Up @@ -439,7 +437,7 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
ctx.Diags.diagnose(loc, diag::module_api_import_conformance,
rootConf->getType(), rootConf->getProtocol(),
importedVia, sourceModule,
importedVia->getTopLevelModule() == sourceModule);
importedVia == sourceModule);
});

auto originKind = getDisallowedOriginKind(ext, where);
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2778,7 +2778,7 @@ void swift::recordRequiredImportAccessLevelForDecl(const ValueDecl *decl,
*sourceModule = decl->getModuleContext();
dc->getASTContext().Diags.diagnose(
diagLoc, diag::module_api_import, decl, importedVia, sourceModule,
importedVia->getTopLevelModule() == sourceModule, loc.isInvalid());
importedVia == sourceModule, loc.isInvalid());
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: B2
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
Expand All @@ -168,7 +170,9 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: B2
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
Expand All @@ -183,7 +187,9 @@ d1_t b2d(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: B2
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ import A2.B2.C2
// DUMP-NEXT: SwiftOnoneSupport
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: E1
// DUMP-NEXT: A1
// DUMP-NEXT: B2
// DUMP-NEXT: A2
// DUMP-NEXT: C2
// DUMP-NEXT: A2

public func callUnsafe(_ p: UnsafeMutableRawPointer) {
let _ = a1(p, 13)
Expand Down Expand Up @@ -290,7 +295,10 @@ c2_t b2_2(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: A1
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
// DUMP-NEXT: _StringProcessing
Expand All @@ -305,7 +313,10 @@ c2_t b2_2(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: A1
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
// DUMP-NEXT: _StringProcessing
Expand Down Expand Up @@ -333,7 +344,10 @@ e2_t c2(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: A1
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
// DUMP-NEXT: _StringProcessing
Expand All @@ -357,7 +371,10 @@ e2_t d2(void * _Nonnull __sized_by(size), int size);
// DUMP-NEXT: D1
// DUMP-NEXT: A1
// DUMP-NEXT: C1
// DUMP-NEXT: A1
// DUMP-NEXT: B1
// DUMP-NEXT: A1
// DUMP-NEXT: A1
// DUMP-CXX-NEXT: CxxShim
// DUMP-CXX-NEXT: Cxx
// DUMP-NEXT: _StringProcessing
Expand Down
109 changes: 0 additions & 109 deletions test/Sema/access-level-import-inconsistent-ordering.swift

This file was deleted.

4 changes: 2 additions & 2 deletions test/Sema/superfluously-public-imports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ public import ClangSubmoduleUnused.ClangSubmoduleUnsuedSubmodule // expected-war
public import ClangTopModule.ClangTopModuleSubmodule

public func clangUser(a: ClangSimpleType) {} // expected-remark {{struct 'ClangSimpleType' is imported via 'ClangSimple'}}
public func clangUser(a: ClangSubmoduleSubmoduleType) {} // expected-remark {{struct 'ClangSubmoduleSubmoduleType' is imported via 'ClangSubmoduleSubmodule'}}
public func clangUser(a: ClangTopModuleType) {} // expected-remark {{struct 'ClangTopModuleType' is imported via 'ClangTopModuleSubmodule'}}
public func clangUser(a: ClangSubmoduleSubmoduleType) {} // expected-remark {{struct 'ClangSubmoduleSubmoduleType' is imported via 'ClangSubmodule'}}
public func clangUser(a: ClangTopModuleType) {} // expected-remark {{struct 'ClangTopModuleType' is imported via 'ClangTopModule'}}

//--- ClientOfClangReexportedSubmodules.swift
public import ClangReexportedSubmodulePublic.ClangReexportedSubmodulePublicSub
Expand Down