mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #78005 from xymus/access-level-import-reexports
Sema: Prioritize @_exported imports over local non-public imports
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
55
test/Sema/access-level-import-exported.swift
Normal file
55
test/Sema/access-level-import-exported.swift
Normal 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) {}
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user