From 772e42e448ce6a63a53727ffa151528fa11cdc5a Mon Sep 17 00:00:00 2001 From: Ellie Shin Date: Mon, 27 Mar 2023 17:04:30 -0700 Subject: [PATCH] Add a missing check for a corner case with package use site / internal decl site Update tests Resolves rdar://106732804, rdar://104987455 --- lib/AST/Decl.cpp | 5 ++ test/Sema/accessibility.swift | 6 +- test/Sema/accessibility_package.swift | 74 ++++++++-------- test/Sema/accessibility_package_inline.swift | 88 +++++++++----------- test/attr/accessibility_proto.swift | 26 ++++++ 5 files changed, 111 insertions(+), 88 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 1cb4ab7b3a3..c152dcb4617 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4112,6 +4112,11 @@ static bool checkAccess(const DeclContext *useDC, const ValueDecl *VD, } return true; case AccessLevel::Internal: { + // Invalid if the use site is > Internal. + // E.g. extension containing a member of a protocol it conforms to has + // `package` access level but the member is `internal` + if (useDC->getContextKind() == DeclContextKind::Package) + return false; const ModuleDecl *sourceModule = sourceDC->getParentModule(); const DeclContext *useFile = useDC->getModuleScopeContext(); if (useFile->getParentModule() == sourceModule) diff --git a/test/Sema/accessibility.swift b/test/Sema/accessibility.swift index 013ce2a0cf4..14e23f8ac03 100644 --- a/test/Sema/accessibility.swift +++ b/test/Sema/accessibility.swift @@ -1471,7 +1471,11 @@ public class DerivedFromInternalConcreteGenericComposition : InternalConcreteGen public func publicReq() {} } -// FIXME: rdar://104987455 should have expected note and error 'class cannot be declared public because its superclass is internal' +fileprivate typealias FilePrivateConcreteGenericCompositionPkg = InternalGenericClass & InternalProto +public class DerivedFromFilePrivateConcreteGenericCompositionPkg : FilePrivateConcreteGenericCompositionPkg { // expected-error {{class cannot be declared public because its superclass uses an internal type as a generic parameter}} + public func internalReq() {} +} + internal typealias InternalConcreteGenericCompositionPkg = PackageGenericClass & PackageProto public class DerivedFromInternalConcreteGenericCompositionPkg : InternalConcreteGenericCompositionPkg { // expected-error {{class cannot be declared public because its superclass uses a package type as a generic parameter}} public func packageReq() {} diff --git a/test/Sema/accessibility_package.swift b/test/Sema/accessibility_package.swift index fa42ce16853..b3254d3fda1 100644 --- a/test/Sema/accessibility_package.swift +++ b/test/Sema/accessibility_package.swift @@ -1,34 +1,18 @@ // RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: split-file %s %t -// RUN: %target-swift-frontend -module-name Utils %t/Utils.swift -emit-module -emit-module-path %t/Utils.swiftmodule -package-name myLib +// RUN: %target-swift-frontend -verify -module-name Utils %t/Utils.swift -emit-module -emit-module-path %t/Utils.swiftmodule -package-name myLib // RUN: test -f %t/Utils.swiftmodule -// RUN: %target-swift-frontend -module-name LibGood %t/LibGood.swift -emit-module -emit-module-path %t/LibGood.swiftmodule -package-name myLib -I %t +// RUN: %target-swift-frontend -verify -module-name LibGood %t/LibGood.swift -emit-module -emit-module-path %t/LibGood.swiftmodule -package-name myLib -I %t // RUN: test -f %t/LibGood.swiftmodule -// RUN: not %target-swift-frontend -module-name Client %t/Client.swift -emit-module -emit-module-path %t/Client.swiftmodule -package-name client -I %t 2> %t/resultClient.output -// RUN: %FileCheck %s -input-file %t/resultClient.output -check-prefix CHECK-CLIENT -// CHECK-CLIENT: error: 'pkgVar' is inaccessible due to 'package' protection level -// CHECK-CLIENT: error: 'pkgFunc' is inaccessible due to 'package' protection level +// RUN: %target-swift-frontend -verify -module-name Client %t/Client.swift -emit-module -emit-module-path %t/Client.swiftmodule -package-name client -I %t -// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -package-name myLib -I %t 2> %t/result1.output -// RUN: %FileCheck %s -input-file %t/result1.output -check-prefix CHECK-1 -// CHECK-1: error: overriding non-open instance method outside of its defining module -// CHECK-1: error: overriding non-open instance method outside of its defining module -// CHECK-1: error: cannot inherit from non-open class 'PublicKlass' outside of its defining module -// CHECK-1: error: cannot inherit from non-open class 'PackageKlass' outside of its defining module -// CHECK-1: error: cannot assign to property: 'publicGetInternal' setter is inaccessible -// CHECK-1: error: cannot assign to property: 'pkgVar' setter is inaccessible +// RUN: %target-swift-frontend -typecheck -verify %t/LibSamePackage.swift -package-name myLib -I %t +// RUN: %target-swift-frontend -typecheck -verify %t/LibOtherPackage.swift -package-name "otherLib" -I %t -// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -package-name "otherLib" -I %t 2> %t/result2.output -// %FileCheck %s -input-file %t/result2.output -check-prefix CHECK-2 -// CHECK-2: error: cannot find type 'PackageProto' in scope -// CHECK-2: error: 'pkgFunc' is inaccessible due to 'package' protection level -// CHECK-2: error: cannot find 'PackageKlass' in scope - - -// BEGIN Utils.swift +//--- Utils.swift package protocol PackageProto { var pkgVar: Double { get set } func pkgFunc() @@ -59,24 +43,24 @@ open class OpenKlass { package func packageFunc() {} } -// BEGIN Lib.swift +//--- LibSamePackage.swift import Utils // Test accessing public and package decls public func test() { let x = PublicKlass() x.publicFunc() - x.pkgFunc() // Allowed if in same package - x.publicGetPkg = 3 // Allowed if in same package - x.publicGetInternal = 4 // Not allowed + x.pkgFunc() // OK + x.publicGetPkg = 3 // OK + x.publicGetInternal = 4 // expected-error {{cannot assign to property: 'publicGetInternal' setter is inaccessible}} - let y = PackageKlass() // Allowed if in same package - y.pkgVar = 1.5 // Not allowed - y.pkgFunc() // Allowed if in same package + let y = PackageKlass() // OK + y.pkgVar = 1.5 // expected-error {{cannot assign to property: 'pkgVar' setter is inaccessible}} + y.pkgFunc() // OK } // Test conformance to a package protocol -package struct LibStruct : PackageProto { // Allowed if in same package +package struct LibStruct : PackageProto { // OK package var pkgVar: Double = 1.0 package func pkgFunc() {} } @@ -84,15 +68,27 @@ package struct LibStruct : PackageProto { // Allowed if in same package // Test subclassing / overrides class SubOpenKlass: OpenKlass { override open func openFunc() {} - override public func publicFunc() {} - override package func packageFunc() {} + override public func publicFunc() {} // expected-error {{overriding non-open instance method outside of its defining module}} + override package func packageFunc() {} // expected-error {{overriding non-open instance method outside of its defining module}} } -class SubPublicKlass: PublicKlass {} // Not allowed -class SubPackageKlass: PackageKlass {} // Not allowed +class SubPublicKlass: PublicKlass {} // expected-error {{cannot inherit from non-open class 'PublicKlass' outside of its defining module}} +class SubPackageKlass: PackageKlass {} // expected-error {{cannot inherit from non-open class 'PackageKlass' outside of its defining module}} +//--- LibOtherPackage.swift +import Utils -// BEGIN LibGood.swift +// Test accessing package decls +public func test() { + let x = PublicKlass() + x.publicFunc() // OK + x.pkgFunc() // expected-error {{'pkgFunc' is inaccessible due to 'package' protection level}} + let y = PackageKlass() // expected-error {{cannot find 'PackageKlass' in scope}} +} + +package struct LibStruct : PackageProto {} // expected-error {{cannot find type 'PackageProto' in scope}} + +//--- LibGood.swift import Utils public func libFunc() { @@ -107,13 +103,13 @@ public struct LibStruct: PackageProto { public func publicFunc() {} } -// BEGIN Client.swift +//--- Client.swift import LibGood func clientFunc() { let lib = LibStruct() - _ = lib.pkgVar // Not allowed + _ = lib.pkgVar // expected-error {{'pkgVar' is inaccessible due to 'package' protection level}} _ = lib.publicVar - lib.pkgFunc() // Not allowed + lib.pkgFunc() // expected-error {{'pkgFunc' is inaccessible due to 'package' protection level}} lib.publicFunc() } diff --git a/test/Sema/accessibility_package_inline.swift b/test/Sema/accessibility_package_inline.swift index f9e407e844f..18c45e1fc1a 100644 --- a/test/Sema/accessibility_package_inline.swift +++ b/test/Sema/accessibility_package_inline.swift @@ -1,53 +1,22 @@ // RUN: %empty-directory(%t) -// RUN: %{python} %utils/split_file.py -o %t %s +// RUN: split-file %s %t -// RUN: %target-swift-frontend -module-name UtilsGood %t/UtilsGood.swift -emit-module -emit-module-path %t/UtilsGood.swiftmodule -package-name myLib +// RUN: %target-swift-frontend -verify -module-name UtilsGood %t/UtilsGood.swift -emit-module -emit-module-path %t/UtilsGood.swiftmodule -package-name myLib // RUN: test -f %t/UtilsGood.swiftmodule -// RUN: not %target-swift-frontend -typecheck %t/Utils.swift -package-name myLib -I %t 2> %t/resultUtils.output -// RUN: %FileCheck %s -input-file %t/resultUtils.output -check-prefix CHECK-UTILS -// CHECK-UTILS: error: class 'PackageKlass' is package and cannot be referenced from an '@inlinable' function -// CHECK-UTILS: let a = PackageKlass() -// CHECK-UTILS: ^ -// CHECK-UTILS: note: class 'PackageKlass' is not '@usableFromInline' or public -// CHECK-UTILS: package class PackageKlass { -// CHECK-UTILS: ^ -// CHECK-UTILS: error: initializer 'init()' is package and cannot be referenced from an '@inlinable' function -// CHECK-UTILS: let a = PackageKlass() // should error -// CHECK-UTILS: ^ -// CHECK-UTILS: note: initializer 'init()' is not '@usableFromInline' or public -// CHECK-UTILS: package init() {} -// CHECK-UTILS: ^ -// CHECK-UTILS: error: class 'InternalKlass' is internal and cannot be referenced from an '@inlinable' function -// CHECK-UTILS: let b = InternalKlass() // should error -// CHECK-UTILS: ^ -// CHECK-UTILS: note: class 'InternalKlass' is not '@usableFromInline' or public -// CHECK-UTILS: class InternalKlass { -// CHECK-UTILS: ^ -// CHECK-UTILS: error: initializer 'init()' is internal and cannot be referenced from an '@inlinable' function -// CHECK-UTILS: let b = InternalKlass() // should error -// CHECK-UTILS: ^ -// CHECK-UTILS: note: initializer 'init()' is not '@usableFromInline' or public -// CHECK-UTILS: init() {} -// CHECK-UTILS: ^ +// RUN: %target-swift-frontend -typecheck -verify %t/Utils.swift -package-name myLib -I %t +// RUN: %target-swift-frontend -typecheck -verify %t/LibOtherPackage.swift -package-name otherLib -I %t +// RUN: %target-swift-frontend -typecheck -verify %t/LibSamePackage.swift -package-name myLib -I %t -// RUN: not %target-swift-frontend -typecheck %t/Lib.swift -package-name "otherLib" -I %t 2> %t/resultLib.output -// %FileCheck %s -input-file %t/resultLib.output -check-prefix CHECK-LIB -// CHECK-LIB: error: cannot find 'packageFunc' in scope -// CHECK-LIB: packageFunc() -// CHECK-LIB: ^~~~~~~~~~~ - -// RUN: %target-swift-frontend -module-name Lib %t/Lib.swift -emit-module -emit-module-path %t/Lib.swiftmodule -package-name myLib -I %t -// RUN: test -f %t/Lib.swiftmodule - -// BEGIN Utils.swift +//--- Utils.swift package protocol PackageProto { var pkgVar: Double { get set } func pkgFunc() } +// expected-note@+1 *{{class 'PackageKlass' is not '@usableFromInline' or public}} package class PackageKlass { - package init() {} + package init() {} // expected-note *{{initializer 'init()' is not '@usableFromInline' or public}} package private(set) var pkgVar: Double = 1.0 package func pkgFunc() {} } @@ -71,8 +40,10 @@ protocol InternalProto { var internalVar: Double { get set } func internalFunc() } + +// expected-note@+1 *{{class 'InternalKlass' is not '@usableFromInline' or public}} class InternalKlass { - init() {} + init() {} // expected-note *{{initializer 'init()' is not '@usableFromInline' or public}} } @usableFromInline class InternalKlassProto: InternalProto { @@ -90,8 +61,12 @@ class InternalKlassForInline { @inlinable public func publicFunc() { - let a = PackageKlass() // should error + let a = PackageKlass() + // expected-error@-1 {{class 'PackageKlass' is package and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} let b = InternalKlass() // should error + // expected-error@-1 {{class 'InternalKlass' is internal and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}} let c = PackageKlassProto() let d = InternalKlassProto() let e = PackageKlassForInline() @@ -101,8 +76,12 @@ public func publicFunc() { @inlinable func internalFunc() { - let a = PackageKlass() // should error - let b = InternalKlass() // should error + let a = PackageKlass() + // expected-error@-1 {{class 'PackageKlass' is package and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} + let b = InternalKlass() + // expected-error@-1 {{class 'InternalKlass' is internal and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}} let c = PackageKlassProto() let d = InternalKlassProto() let e = PackageKlassForInline() @@ -112,8 +91,12 @@ func internalFunc() { @inlinable package func packageFunc() { - let a = PackageKlass() // should error - let b = InternalKlass() // should error + let a = PackageKlass() + // expected-error@-1 {{class 'PackageKlass' is package and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is package and cannot be referenced from an '@inlinable' function}} + let b = InternalKlass() + // expected-error@-1 {{class 'InternalKlass' is internal and cannot be referenced from an '@inlinable' function}} + // expected-error@-2 {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}} let c = PackageKlassProto() let d = InternalKlassProto() let e = PackageKlassForInline() @@ -121,7 +104,7 @@ package func packageFunc() { print(a, b, c, d, e, f) } -// BEGIN UtilsGood.swift +//--- UtilsGood.swift package protocol PackageProto { var pkgVar: Double { get set } func pkgFunc() @@ -170,11 +153,20 @@ package func packageFunc() { print(x, y) } -// BEGIN Lib.swift +//--- LibOtherPackage.swift import UtilsGood @inlinable public func libFunc() { publicFunc() - packageFunc() // Allowed if in same package + packageFunc() // expected-error {{cannot find 'packageFunc' in scope}} +} + +//--- LibSamePackage.swift +import UtilsGood + +@inlinable +public func libFunc() { + publicFunc() + packageFunc() // OK } diff --git a/test/attr/accessibility_proto.swift b/test/attr/accessibility_proto.swift index 78fe2d4a834..e2206f61fa8 100644 --- a/test/attr/accessibility_proto.swift +++ b/test/attr/accessibility_proto.swift @@ -243,3 +243,29 @@ package protocol PkgEmptyInit { public struct PkgBuggy: PkgEmptyInit { // expected-error@-1 {{initializer 'init()' must be declared package because it matches a requirement in package protocol 'PkgEmptyInit'}} } + +package protocol PkgReqProvider {} +extension PkgReqProvider { + fileprivate func foo() {} + // expected-note@-1 {{mark the instance method as 'package' to satisfy the requirement}} {{3-14=package}} + typealias AssocB = String + // expected-note@-1 {{mark the type alias as 'package' to satisfy the requirement}} {{3-3=package }} +} +package struct PkgAdoptViaProtocol : PkgProtoWithReqs, PkgReqProvider { + // expected-error@-1 {{method 'foo()' must be declared package because it matches a requirement in package protocol 'PkgProtoWithReqs'}} {{none}} + // expected-error@-2 {{type alias 'AssocB' must be declared package because it matches a requirement in package protocol 'PkgProtoWithReqs'}} {{none}} + package typealias AssocA = Int +} + +package protocol PkgReqProvider2 {} +extension PkgProtoWithReqs where Self : PkgReqProvider2 { + func foo() {} + // expected-note@-1 {{mark the instance method as 'package' to satisfy the requirement}} {{3-3=package }} + typealias AssocB = String + // expected-note@-1 {{mark the type alias as 'package' to satisfy the requirement}} {{3-3=package }} +} +package struct PkgAdoptViaCombinedProtocol : PkgProtoWithReqs, PkgReqProvider2 { + // expected-error@-1 {{method 'foo()' must be declared package because it matches a requirement in package protocol 'PkgProtoWithReqs'}} {{none}} + // expected-error@-2 {{type alias 'AssocB' must be declared package because it matches a requirement in package protocol 'PkgProtoWithReqs'}} {{none}} + public typealias AssocA = Int +}