Skip to content

Commit

Permalink
Merge pull request swiftlang#78718 from xymus/fix-importing-non-visib…
Browse files Browse the repository at this point in the history
…le-decls-6.1

[6.1] Sema: Ensure access-level on imports only applies to visible imported decls
  • Loading branch information
xymus authored Jan 22, 2025
2 parents b0c7f61 + 5b6ab66 commit dc74591
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4660,7 +4660,11 @@ getAccessScopeForFormalAccess(const ValueDecl *VD,
if (localImportRestriction.has_value()) {
AccessLevel importAccessLevel =
localImportRestriction.value().accessLevel;
if (access > importAccessLevel) {
auto isVisible = access >= AccessLevel::Public ||
(access == AccessLevel::Package &&
useDC->getParentModule()->inSamePackage(resultDC->getParentModule()));

if (access > importAccessLevel && isVisible) {
access = std::min(access, importAccessLevel);
resultDC = useDC->getParentSourceFile();
}
Expand Down
156 changes: 156 additions & 0 deletions test/Sema/access-level-import-downgrades.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/// Ensure we only bump down the access-level of imported decls, not up.

// RUN: %empty-directory(%t)
// RUN: split-file %s %t

/// Build libraries
// RUN: %target-swift-frontend -emit-module %t/ImportedPrivate.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -package-name pkg \
// RUN: -emit-module-path %t/ImportedPrivate.swiftmodule
// RUN: %target-swift-frontend -emit-module %t/ImportedInternal.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -package-name pkg \
// RUN: -emit-module-path %t/ImportedInternal.swiftmodule -I %t
// RUN: %target-swift-frontend -emit-module %t/ImportedPackage.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -package-name pkg \
// RUN: -emit-module-path %t/ImportedPackage.swiftmodule -I %t
// RUN: %target-swift-frontend -emit-module %t/ImportedPublic.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -package-name pkg \
// RUN: -emit-module-path %t/ImportedPublic.swiftmodule -I %t

/// Build clients
// RUN: %target-swift-frontend -typecheck %t/InPackageClient.swift -I %t \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -package-name pkg -verify
// RUN: %target-swift-frontend -typecheck %t/OutOfPackageClient.swift -I %t \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -verify

//--- ImportedPrivate.swift

private func privateFunc() {}
internal func internalFunc() {}
package func packageFunc() {}
public func publicFunc() {}

//--- ImportedInternal.swift

private func privateFunc() {}
internal func internalFunc() {}
package func packageFunc() {}
public func publicFunc() {}

//--- ImportedPackage.swift

private func privateFunc() {}
internal func internalFunc() {}
package func packageFunc() {}
public func publicFunc() {}

//--- ImportedPublic.swift

private func privateFunc() {}
internal func internalFunc() {}
package func packageFunc() {}
public func publicFunc() {}

//--- InPackageClient.swift

private import ImportedPrivate
internal import ImportedInternal
private import ImportedPackage
public import ImportedPublic // expected-warning{{public import of 'ImportedPublic' was not used in public declarations or inlinable code}}

ImportedPrivate.privateFunc() // expected-error {{module 'ImportedPrivate' has no member named 'privateFunc'}}
ImportedPrivate.internalFunc() // expected-error {{module 'ImportedPrivate' has no member named 'internalFunc'}}
ImportedPrivate.packageFunc()
ImportedPrivate.publicFunc()

ImportedInternal.privateFunc() // expected-error {{module 'ImportedInternal' has no member named 'privateFunc'}}
ImportedInternal.internalFunc() // expected-error {{module 'ImportedInternal' has no member named 'internalFunc'}}
ImportedInternal.packageFunc()
ImportedInternal.publicFunc()

ImportedPackage.privateFunc() // expected-error {{module 'ImportedPackage' has no member named 'privateFunc'}}
ImportedPackage.internalFunc() // expected-error {{module 'ImportedPackage' has no member named 'internalFunc'}}
ImportedPackage.packageFunc()
ImportedPackage.publicFunc()

ImportedPublic.privateFunc() // expected-error {{module 'ImportedPublic' has no member named 'privateFunc'}}
ImportedPublic.internalFunc() // expected-error {{module 'ImportedPublic' has no member named 'internalFunc'}}
ImportedPublic.packageFunc()
ImportedPublic.publicFunc()

func funcContext() {
ImportedPrivate.privateFunc() // expected-error {{module 'ImportedPrivate' has no member named 'privateFunc'}}
ImportedPrivate.internalFunc() // expected-error {{module 'ImportedPrivate' has no member named 'internalFunc'}}
ImportedPrivate.packageFunc()
ImportedPrivate.publicFunc()

ImportedInternal.privateFunc() // expected-error {{module 'ImportedInternal' has no member named 'privateFunc'}}
ImportedInternal.internalFunc() // expected-error {{module 'ImportedInternal' has no member named 'internalFunc'}}
ImportedInternal.packageFunc()
ImportedInternal.publicFunc()

ImportedPackage.privateFunc() // expected-error {{module 'ImportedPackage' has no member named 'privateFunc'}}
ImportedPackage.internalFunc() // expected-error {{module 'ImportedPackage' has no member named 'internalFunc'}}
ImportedPackage.packageFunc()
ImportedPackage.publicFunc()

ImportedPublic.privateFunc() // expected-error {{module 'ImportedPublic' has no member named 'privateFunc'}}
ImportedPublic.internalFunc() // expected-error {{module 'ImportedPublic' has no member named 'internalFunc'}}
ImportedPublic.packageFunc()
ImportedPublic.publicFunc()
}

//--- OutOfPackageClient.swift

private import ImportedPrivate
internal import ImportedInternal
private import ImportedPackage
public import ImportedPublic // expected-warning{{public import of 'ImportedPublic' was not used in public declarations or inlinable code}}

ImportedPrivate.privateFunc() // expected-error {{module 'ImportedPrivate' has no member named 'privateFunc'}}
ImportedPrivate.internalFunc() // expected-error {{module 'ImportedPrivate' has no member named 'internalFunc'}}
ImportedPrivate.packageFunc() // expected-error {{module 'ImportedPrivate' has no member named 'packageFunc'}}
ImportedPrivate.publicFunc()

ImportedInternal.privateFunc() // expected-error {{module 'ImportedInternal' has no member named 'privateFunc'}}
ImportedInternal.internalFunc() // expected-error {{module 'ImportedInternal' has no member named 'internalFunc'}}
ImportedInternal.packageFunc() // expected-error {{module 'ImportedInternal' has no member named 'packageFunc'}}
ImportedInternal.publicFunc()

ImportedPackage.privateFunc() // expected-error {{module 'ImportedPackage' has no member named 'privateFunc'}}
ImportedPackage.internalFunc() // expected-error {{module 'ImportedPackage' has no member named 'internalFunc'}}
ImportedPackage.packageFunc() // expected-error {{module 'ImportedPackage' has no member named 'packageFunc'}}
ImportedPackage.publicFunc()

ImportedPublic.privateFunc() // expected-error {{module 'ImportedPublic' has no member named 'privateFunc'}}
ImportedPublic.internalFunc() // expected-error {{module 'ImportedPublic' has no member named 'internalFunc'}}
ImportedPublic.packageFunc() // expected-error {{module 'ImportedPublic' has no member named 'packageFunc'}}
ImportedPublic.publicFunc()

func funcContext() {
ImportedPrivate.privateFunc() // expected-error {{module 'ImportedPrivate' has no member named 'privateFunc'}}
ImportedPrivate.internalFunc() // expected-error {{module 'ImportedPrivate' has no member named 'internalFunc'}}
ImportedPrivate.packageFunc() // expected-error {{module 'ImportedPrivate' has no member named 'packageFunc'}}
ImportedPrivate.publicFunc()

ImportedInternal.privateFunc() // expected-error {{module 'ImportedInternal' has no member named 'privateFunc'}}
ImportedInternal.internalFunc() // expected-error {{module 'ImportedInternal' has no member named 'internalFunc'}}
ImportedInternal.packageFunc() // expected-error {{module 'ImportedInternal' has no member named 'packageFunc'}}
ImportedInternal.publicFunc()

ImportedPackage.privateFunc() // expected-error {{module 'ImportedPackage' has no member named 'privateFunc'}}
ImportedPackage.internalFunc() // expected-error {{module 'ImportedPackage' has no member named 'internalFunc'}}
ImportedPackage.packageFunc() // expected-error {{module 'ImportedPackage' has no member named 'packageFunc'}}
ImportedPackage.publicFunc()

ImportedPublic.privateFunc() // expected-error {{module 'ImportedPublic' has no member named 'privateFunc'}}
ImportedPublic.internalFunc() // expected-error {{module 'ImportedPublic' has no member named 'internalFunc'}}
ImportedPublic.packageFunc() // expected-error {{module 'ImportedPublic' has no member named 'packageFunc'}}
ImportedPublic.publicFunc()
}
44 changes: 44 additions & 0 deletions test/Sema/private-import-ambiguities.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

/// Build libraries
// RUN: %target-swift-frontend -emit-module %t/LibShared.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -emit-module-path %t/LibShared.swiftmodule
// RUN: %target-swift-frontend -emit-module %t/LibWithPublicFoo.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -emit-module-path %t/LibWithPublicFoo.swiftmodule -I %t
// RUN: %target-swift-frontend -emit-module %t/LibWithInternalFoo.swift \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -emit-module-path %t/LibWithInternalFoo.swiftmodule -I %t

/// Build client
// RUN: %target-swift-frontend -typecheck %t/Client.swift -I %t \
// RUN: -enable-library-evolution -swift-version 5

//--- LibShared.swift
public struct Struct {
public init() {}
}

//--- LibWithPublicFoo.swift
import LibShared

extension Struct {
public func foo() {}
}

//--- LibWithInternalFoo.swift
import LibShared

extension Struct {
internal func foo() {}
}

//--- Client.swift
import LibShared
import LibWithPublicFoo
private import LibWithInternalFoo

var s = Struct()
s.foo() // This is non-ambiguous

0 comments on commit dc74591

Please sign in to comment.