Skip to content

Sema: Avoid diagnosing potential unavailability of type components of unavailable decls #58417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
5 changes: 5 additions & 0 deletions lib/Sema/TypeCheckAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,11 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
// Don't bother checking errors.
if (type && type->hasError())
return;

// If the decl which references this type is unavailable on the current
// platform, don't diagnose the availability of the type.
if (AvailableAttr::isUnavailable(context))
return;

DeclAvailabilityFlags flags = None;

Expand Down
67 changes: 64 additions & 3 deletions test/Sema/availability_versions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,9 @@ enum CompassPoint {
case WithPotentiallyUnavailablePayload(p : EnumIntroducedOn10_52) // expected-error {{'EnumIntroducedOn10_52' is only available in macOS 10.52 or newer}}

case WithPotentiallyUnavailablePayload1(p : EnumIntroducedOn10_52), WithPotentiallyUnavailablePayload2(p : EnumIntroducedOn10_52) // expected-error 2{{'EnumIntroducedOn10_52' is only available in macOS 10.52 or newer}}

@available(OSX, unavailable)
case WithPotentiallyUnavailablePayload3(p : EnumIntroducedOn10_52)
}

@available(OSX, introduced: 10.52)
Expand Down Expand Up @@ -712,7 +715,7 @@ func classViaTypeParameter() {
// Potentially unavailable class used in declarations

class ClassWithDeclarationsOfPotentiallyUnavailableClasses {
// expected-note@-1 5{{add @available attribute to enclosing class}}
// expected-note@-1 6{{add @available attribute to enclosing class}}

@available(OSX, introduced: 10.51)
init() {}
Expand All @@ -738,11 +741,20 @@ class ClassWithDeclarationsOfPotentiallyUnavailableClasses {
return ClassAvailableOn10_51() // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
}

@available(OSX, unavailable)
func unavailableMethodWithPotentiallyUnavailableParameterType(_ o : ClassAvailableOn10_51) {}

@available(OSX, introduced: 10.51)
func potentiallyUnavailableMethodWithPotentiallyUnavailableReturnType() -> ClassAvailableOn10_51 {
return ClassAvailableOn10_51()
}

@available(OSX, unavailable)
func unavailableMethodWithPotentiallyUnavailableReturnType() -> ClassAvailableOn10_51 {
guard #available(OSX 10.51, *) else { fatalError() }
return ClassAvailableOn10_51()
}

func methodWithPotentiallyUnavailableLocalDeclaration() {
// expected-note@-1 {{add @available attribute to enclosing instance method}}
Expand All @@ -754,6 +766,12 @@ class ClassWithDeclarationsOfPotentiallyUnavailableClasses {
func potentiallyUnavailableMethodWithPotentiallyUnavailableLocalDeclaration() {
let _ : ClassAvailableOn10_51 = methodWithPotentiallyUnavailableReturnType()
}

@available(OSX, unavailable)
func unavailableMethodWithPotentiallyUnavailableLocalDeclaration() {
let _ : ClassAvailableOn10_51 = methodWithPotentiallyUnavailableReturnType() // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 {{add 'if #available' version check}}
}
}

func referToPotentiallyUnavailableStaticProperty() {
Expand All @@ -770,6 +788,10 @@ class ClassExtendingPotentiallyUnavailableClass : ClassAvailableOn10_51 { // exp
class PotentiallyUnavailableClassExtendingPotentiallyUnavailableClass : ClassAvailableOn10_51 {
}

@available(OSX, unavailable)
class UnavailableClassExtendingPotentiallyUnavailableClass : ClassAvailableOn10_51 {
}

// Method availability is contravariant

class SuperWithAlwaysAvailableMembers {
Expand Down Expand Up @@ -857,6 +879,17 @@ class SubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability {
}
}

@available(OSX, unavailable)
class UnavailableSubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability {
override func someMethod() {
}

override var someProperty: Int {
get { return 5 }
set(newVal) {}
}
}

// Inheritance and availability

@available(OSX, introduced: 10.51)
Expand All @@ -875,10 +908,18 @@ protocol ProtocolAvailableOn10_9InheritingFromProtocolAvailableOn10_51 : Protoco
protocol ProtocolAvailableOn10_51InheritingFromProtocolAvailableOn10_9 : ProtocolAvailableOn10_9 {
}

@available(OSX, unavailable)
protocol UnavailableProtocolInheritingFromProtocolAvailableOn10_51 : ProtocolAvailableOn10_51 {
}

@available(OSX, introduced: 10.9)
class SubclassAvailableOn10_9OfClassAvailableOn10_51 : ClassAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
}

@available(OSX, unavailable)
class UnavailableSubclassOfClassAvailableOn10_51 : ClassAvailableOn10_51 {
}

// We allow nominal types to conform to protocols that are less available than the types themselves.
@available(OSX, introduced: 10.9)
class ClassAvailableOn10_9AdoptingProtocolAvailableOn10_51 : ProtocolAvailableOn10_51 {
Expand All @@ -896,7 +937,7 @@ func castToPotentiallyUnavailableProtocol() {
}

@available(OSX, introduced: 10.9)
class SubclassAvailableOn10_9OfClassAvailableOn10_51AlsoAdoptingProtocolAvailableOn10_51 : ClassAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
class SubclassAvailableOn10_9OfClassAvailableOn10_51AlsoAdoptingProtocolAvailableOn10_51 : ClassAvailableOn10_51, ProtocolAvailableOn10_51 { // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
}

class SomeGenericClass<T> { }
Expand All @@ -905,27 +946,48 @@ class SomeGenericClass<T> { }
class SubclassAvailableOn10_9OfSomeGenericClassOfProtocolAvailableOn10_51 : SomeGenericClass<ProtocolAvailableOn10_51> { // expected-error {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}}
}

@available(OSX, unavailable)
class UnavailableSubclassOfSomeGenericClassOfProtocolAvailableOn10_51 : SomeGenericClass<ProtocolAvailableOn10_51> {
}

func GenericWhereClause<T>(_ t: T) where T: ProtocolAvailableOn10_51 { // expected-error * {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 * {{add @available attribute to enclosing global function}}
}

@available(OSX, unavailable)
func UnavailableGenericWhereClause<T>(_ t: T) where T: ProtocolAvailableOn10_51 {
}

func GenericSignature<T : ProtocolAvailableOn10_51>(_ t: T) { // expected-error * {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 * {{add @available attribute to enclosing global function}}
}

@available(OSX, unavailable)
func UnavailableGenericSignature<T : ProtocolAvailableOn10_51>(_ t: T) {
}

struct GenericType<T> { // expected-note {{add @available attribute to enclosing generic struct}}
func nonGenericWhereClause() where T : ProtocolAvailableOn10_51 {} // expected-error {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing instance method}}

@available(OSX, unavailable)
func unavailableNonGenericWhereClause() where T : ProtocolAvailableOn10_51 {}

struct NestedType where T : ProtocolAvailableOn10_51 {} // expected-error {{'ProtocolAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 2{{add @available attribute to enclosing struct}}

@available(OSX, unavailable)
struct UnavailableNestedType where T : ProtocolAvailableOn10_51 {}
}

// Extensions

extension ClassAvailableOn10_51 { } // expected-error {{'ClassAvailableOn10_51' is only available in macOS 10.51 or newer}}
// expected-note@-1 {{add @available attribute to enclosing extension}}

@available(OSX, unavailable)
extension ClassAvailableOn10_51 { }

@available(OSX, introduced: 10.51)
extension ClassAvailableOn10_51 {
func m() {
Expand Down Expand Up @@ -957,7 +1019,6 @@ extension ClassToExtend {
// We allow protocol extensions for protocols that are less available than the
// conforming class.
extension ClassToExtend : ProtocolAvailableOn10_51 {

}

@available(OSX, introduced: 10.51)
Expand Down
33 changes: 32 additions & 1 deletion test/attr/attr_availability_transitive_osx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,42 @@ extension Outer {
}

@available(OSX, unavailable)
struct NotOnOSX {
struct NotOnOSX { // expected-note {{'NotOnOSX' has been explicitly marked unavailable here}}
var osx_init_osx = osx() // OK
lazy var osx_lazy_osx = osx() // OK
var osx_init_multi1_osx = osx(), osx_init_multi2_osx = osx() // OK
var (osx_init_deconstruct1_osx, osx_init_deconstruct2_osx) = osx_pair() // OK
var (_, osx_init_deconstruct2_only_osx) = osx_pair() // OK
var (osx_init_deconstruct1_only_osx, _) = osx_pair() // OK
}

@available(OSX, unavailable)
extension NotOnOSX {
func osx_call_osx() {
osx() // OK
}

func osx_call_osx_extension() {
osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
}
}

@available(OSXApplicationExtension, unavailable)
extension NotOnOSX { } // expected-error {{'NotOnOSX' is unavailable in macOS}}

@available(OSXApplicationExtension, unavailable)
struct NotOnOSXApplicationExtension { }

@available(OSX, unavailable)
extension NotOnOSXApplicationExtension { } // OK; NotOnOSXApplicationExtension is only unavailable if -application-extension is passed.

@available(OSXApplicationExtension, unavailable)
extension NotOnOSXApplicationExtension {
func osx_call_osx() {
osx() // expected-error {{'osx()' is unavailable in macOS}}
}

func osx_call_osx_extension() {
osx_extension() // OK
}
}
38 changes: 36 additions & 2 deletions test/attr/attr_availability_transitive_osx_extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.

@available(OSX, unavailable)
func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
func osx() {} // expected-note 3{{'osx()' has been explicitly marked unavailable here}}

@available(OSXApplicationExtension, unavailable)
func osx_extension() {} // expected-note 2{{'osx_extension()' has been explicitly marked unavailable here}}
func osx_extension() {} // expected-note 3{{'osx_extension()' has been explicitly marked unavailable here}}

func call_osx_extension() {
osx_extension() // expected-error {{'osx_extension()' is unavailable}}
Expand Down Expand Up @@ -35,3 +35,37 @@ func osx_extension_call_osx_extension() {
func osx_extension_call_osx() {
osx() // expected-error {{'osx()' is unavailable}}
}

@available(OSX, unavailable)
struct NotOnOSX { }

@available(OSX, unavailable)
extension NotOnOSX {
func osx_call_osx() {
osx() // OK
}

func osx_call_osx_extension() {
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
}
}

@available(OSXApplicationExtension, unavailable)
extension NotOnOSX { }

@available(OSXApplicationExtension, unavailable)
struct NotOnOSXApplicationExtension { }

@available(OSX, unavailable)
extension NotOnOSXApplicationExtension { }

@available(OSXApplicationExtension, unavailable)
extension NotOnOSXApplicationExtension {
func osx_call_osx() {
osx() // expected-error {{'osx()' is unavailable in macOS}}
}

func osx_call_osx_extension() {
osx_extension() // OK
}
}