Merge pull request #78005 from xymus/access-level-import-reexports

Sema: Prioritize @_exported imports over local non-public imports
This commit is contained in:
Alexis Laferrière
2024-12-09 13:35:44 -08:00
committed by GitHub
3 changed files with 83 additions and 3 deletions

View File

@@ -2957,6 +2957,16 @@ SourceFile::getImportAccessLevel(const ModuleDecl *targetModule) const {
restrictiveImport = import;
}
}
// Reexports from the local module take precedence over non-public imports
// and lift all access-level restrictions. We still prioritize file local
// public imports as diagnostics will have an import to point to and
// they are recommended over indirect imports.
if ((!restrictiveImport.has_value() ||
restrictiveImport->accessLevel < AccessLevel::Public) &&
imports.isImportedBy(targetModule, getParentModule()))
return std::nullopt;
return restrictiveImport;
}

View File

@@ -0,0 +1,55 @@
/// Test that an @_exported import is preferred to local non-public imports.
// RUN: %empty-directory(%t)
// RUN: split-file --leading-lines %s %t
/// Build the libraries.
// RUN: %target-swift-frontend -emit-module %t/TargetLib.swift -o %t
// RUN: %target-swift-frontend -emit-module %t/IndirectLib.swift -I %t -o %t
/// Check acceptable client configurations to access TargetLib publicly.
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportDirect.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportDirect.swift %t/Client_FileReexport.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportDirectAsPrivate.swift %t/Client_FileReexport.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportIndirectModule.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportIndirectModule.swift %t/Client_FileReexport.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportIndirectModuleAsPrivate.swift %t/Client_FileReexport.swift
// RUN: %target-swift-frontend -typecheck -verify -I %t \
// RUN: %t/Client_ImportIndirectLocal.swift %t/Client_FileReexport.swift
//--- TargetLib.swift
public struct TargetType {
public init() {}
}
//--- IndirectLib.swift
@_exported import TargetLib
//--- Client_FileReexport.swift
@_exported public import TargetLib
//--- Client_ImportDirect.swift
public import TargetLib
public func user(t: TargetType) {}
//--- Client_ImportDirectAsPrivate.swift
fileprivate import TargetLib
public func user(t: TargetType) {}
// Unrestricted as it's @_exported elsewhere in the module
//--- Client_ImportIndirectModule.swift
public import IndirectLib
public func user(t: TargetType) {}
//--- Client_ImportIndirectModuleAsPrivate.swift
fileprivate import IndirectLib
public func user(t: TargetType) {}
// Unrestricted as it's @_exported elsewhere in the module
//--- Client_ImportIndirectLocal.swift
public func user(t: TargetType) {}

View File

@@ -17,11 +17,21 @@
/// Client testing order of preference for more levels of imports.
// RUN: %target-swift-frontend -typecheck -I %t \
// RUN: %t/ExportedClient_FileExported.swift %t/ExportedClient_FileA.swift \
// RUN: %t/ExportedClient_FileB.swift %t/ExportedClient_FileC.swift %t/ExportedClient_FileD.swift \
// RUN: %t/ExportedClient_FileB.swift %t/ExportedClient_FileC.swift \
// RUN: %t/ExportedClient_FileD_via_underlying.swift \
// RUN: -import-underlying-module -module-name ExportedClient \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -Rmodule-api-import -verify
// Same without the underlying clang module.
// RUN: %target-swift-frontend -typecheck -I %t \
// RUN: %t/ExportedClient_FileExported.swift %t/ExportedClient_FileA.swift \
// RUN: %t/ExportedClient_FileB.swift %t/ExportedClient_FileC.swift \
// RUN: %t/ExportedClient_FileD_via_exported.swift \
// RUN: -module-name ExportedClient \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -Rmodule-api-import -verify
/// Client testing -public-module-name ordering.
// RUN: %target-swift-frontend -typecheck -I %t \
// RUN: %t/SwiftLibClient_FileA.swift %t/SwiftLibClient_FileB.swift \
@@ -156,11 +166,16 @@ public import NotLib
public func useTypesC(a: ExportedType) {}
// expected-remark @-1 {{struct 'ExportedType' is imported via 'NotLib', which reexports definition from 'LibCore'}}
//--- ExportedClient_FileD.swift
/// Last used the module-wide @_exported import.
//--- ExportedClient_FileD_via_underlying.swift
/// Then use the import of the underling clang module.
public func useTypesD(a: ExportedType) {}
// expected-remark @-1 {{struct 'ExportedType' is imported via 'ExportedClient', which reexports definition from 'LibCore'}}
//--- ExportedClient_FileD_via_exported.swift
/// Finally use the @_exported import from the local module.
public func useTypesD(a: ExportedType) {}
// It would be nice to have a remark even without an import to point to.
//--- SwiftLibClient_FileA.swift
/// Prefer the import matching public-module-name.