From ae21f8d390121ad61ecc22907dd13e60f56b8211 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 9 Apr 2025 19:56:45 -0700 Subject: [PATCH] AST: Stop diagnosing potentially unavailable declarations in unavailable contexts. Potential unavailability of a declaration has always been diagnosed in contexts that do not have a sufficient platform introduction constraint, even when those contexts are also unavailable on the target platform. This behavior is overly strict, since the potential unavailability will never matter, but it's a longstanding quirk of availability checking. As a result, some source code has been written to work around this quirk by marking declarations as simultaneously unavailable and introduced for a given platform: ``` @available(macOS, unavailable, introduced: 15) func unavailableAndIntroducedInMacOS15() { // ... allowed to call functions introduced in macOS 15. } ``` When availability checking was refactored to be based on a constraint engine in https://github.com/swiftlang/swift/pull/79260, the compiler started effectively treating `@available(macOS, unavailable, introduced: 15)` as just `@available(macOS, unavailable)` because the introduction constraint was treated as lower priority and therefore superseded by the unavailability constraint. This caused a regression for the code that was written to work around the availability checker's strictness. We could try to match the behavior from previous releases, but it's actually tricky to match the behavior well enough in the new availability checking architecture to fully fix source compatibility. Consequently, it seems like the best fix is actually to address this long standing issue and stop diagnosing potential unavailability in unavailable contexts. The main risk of this approach is source compatibility for regions of unavailable code. It's theoretically possible that restricting available declarations by introduction version in unavailable contexts is important to prevent ambiguities during overload resolution in some codebases. If we find that is a problem that is too prevalent, we may have to take a different approach. Resolves rdar://147945883. --- CHANGELOG.md | 27 ++++++ lib/AST/AvailabilityConstraint.cpp | 63 +++++++++---- test/Constraints/availability_macos.swift | 37 ++++++++ test/Sema/availability_scopes.swift | 27 ++++-- test/Sema/property_wrapper_availability.swift | 12 +-- .../attr_availability_transitive_osx.swift | 89 +++++++++++-------- ...r_availability_transitive_osx_appext.swift | 3 +- test/attr/attr_inlinable_available.swift | 22 ++--- 8 files changed, 204 insertions(+), 76 deletions(-) create mode 100644 test/Constraints/availability_macos.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index d2bb92dd34743..3ee272369c877 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,33 @@ ## Swift 6.2 +* The Swift compiler no longer diagnoses references to declarations that are + potentially unavailable because the platform version might not be new enough + when those references occur inside of contexts that are also unavailable to + that platform. This addresses a long-standing nuisance for multi-platform + code. However, there is also a chance that existing source code may become + ambiguous as a result: + + ```swift + struct A {} + struct B {} + + func potentiallyAmbiguous(_: A) {} + + @available(macOS 99, *) + func potentiallyAmbiguous(_: B) {} + + @available(macOS, unavailable) + func unavailableOnMacOS() { + potentiallyAmbiguous(.init()) // error: ambiguous use of 'init()' + } + ``` + + Code that is now ambiguous as a result should likely be restructured since + disambiguation based on platform introduction alone has never been a reliable + strategy, given that the code would eventually become ambiguous anyways when + the deployment target is raised. + * [SE-0419][]: Introduced the new `Runtime` module, which contains a public API that can generate backtraces, presently supported on macOS and Linux. Capturing a diff --git a/lib/AST/AvailabilityConstraint.cpp b/lib/AST/AvailabilityConstraint.cpp index 9968cdcf2d34a..5377057ad94ec 100644 --- a/lib/AST/AvailabilityConstraint.cpp +++ b/lib/AST/AvailabilityConstraint.cpp @@ -113,25 +113,59 @@ DeclAvailabilityConstraints::getPrimaryConstraint() const { return result; } +static bool canIgnoreConstraintInUnavailableContexts( + const Decl *decl, const AvailabilityConstraint &constraint) { + auto domain = constraint.getDomain(); + + switch (constraint.getReason()) { + case AvailabilityConstraint::Reason::UnconditionallyUnavailable: + // Always reject uses of universally unavailable declarations, regardless + // of context, since there are no possible compilation configurations in + // which they are available. However, make an exception for types and + // conformances, which can sometimes be awkward to avoid references to. + if (!isa(decl) && !isa(decl)) { + if (domain.isUniversal() || domain.isSwiftLanguage()) + return false; + } + return true; + + case AvailabilityConstraint::Reason::PotentiallyUnavailable: + switch (domain.getKind()) { + case AvailabilityDomain::Kind::Universal: + case AvailabilityDomain::Kind::SwiftLanguage: + case AvailabilityDomain::Kind::PackageDescription: + case AvailabilityDomain::Kind::Embedded: + case AvailabilityDomain::Kind::Custom: + return false; + case AvailabilityDomain::Kind::Platform: + // Platform availability only applies to the target triple that the + // binary is being compiled for. Since the same declaration can be + // potentially unavailable from a given context when compiling for one + // platform, but available from that context when compiling for a + // different platform, it is overly strict to enforce potential platform + // unavailability constraints in contexts that are unavailable to that + // platform. + return true; + } + return constraint.getDomain().isPlatform(); + + case AvailabilityConstraint::Reason::Obsoleted: + case AvailabilityConstraint::Reason::UnavailableForDeployment: + return false; + } +} + static bool -isInsideCompatibleUnavailableDeclaration(const Decl *decl, - const SemanticAvailableAttr &attr, - const AvailabilityContext &context) { +shouldIgnoreConstraintInContext(const Decl *decl, + const AvailabilityConstraint &constraint, + const AvailabilityContext &context) { if (!context.isUnavailable()) return false; - if (!attr.isUnconditionallyUnavailable()) + if (!canIgnoreConstraintInUnavailableContexts(decl, constraint)) return false; - // Refuse calling universally unavailable functions from unavailable code, - // but allow the use of types. - auto domain = attr.getDomain(); - if (!isa(decl) && !isa(decl)) { - if (domain.isUniversal() || domain.isSwiftLanguage()) - return false; - } - - return context.containsUnavailableDomain(domain); + return context.containsUnavailableDomain(constraint.getDomain()); } /// Returns the `AvailabilityConstraint` that describes how \p attr restricts @@ -218,8 +252,7 @@ static void getAvailabilityConstraintsForDecl( // declaration is unconditionally unavailable in a domain for which // the context is already unavailable. llvm::erase_if(constraints, [&](const AvailabilityConstraint &constraint) { - return isInsideCompatibleUnavailableDeclaration(decl, constraint.getAttr(), - context); + return shouldIgnoreConstraintInContext(decl, constraint, context); }); } diff --git a/test/Constraints/availability_macos.swift b/test/Constraints/availability_macos.swift new file mode 100644 index 0000000000000..06e326424ec62 --- /dev/null +++ b/test/Constraints/availability_macos.swift @@ -0,0 +1,37 @@ +// RUN: %target-typecheck-verify-swift + +// REQUIRES: OS=macosx + +struct A {} // expected-note * {{found this candidate}} +struct B {} // expected-note * {{found this candidate}} + +func ambiguousInFarFuture(_: A) {} + +@available(macOS 99, *) +func ambiguousInFarFuture(_: B) {} + +struct S { + func ambiguousInFarFuture(_: A) {} +} + +@available(macOS 99, *) +extension S { + func ambiguousInFarFuture(_: B) {} +} + +func testDeploymentTarget(_ s: S) { + ambiguousInFarFuture(.init()) + s.ambiguousInFarFuture(.init()) +} + +@available(macOS 99, *) +func testFarFuture(_ s: S) { + ambiguousInFarFuture(.init()) // expected-error {{ambiguous use of 'init()'}} + s.ambiguousInFarFuture(.init()) // expected-error {{ambiguous use of 'init()'}} +} + +@available(macOS, unavailable) +func testUnavailable(_ s: S) { + ambiguousInFarFuture(.init()) // expected-error {{ambiguous use of 'init()'}} + s.ambiguousInFarFuture(.init()) // expected-error {{ambiguous use of 'init()'}} +} diff --git a/test/Sema/availability_scopes.swift b/test/Sema/availability_scopes.swift index b3a3ea56964c1..8042beeb145b2 100644 --- a/test/Sema/availability_scopes.swift +++ b/test/Sema/availability_scopes.swift @@ -253,19 +253,19 @@ extension SomeClass { // CHECK-NEXT: {{^}} (decl_implicit version=50 decl=extension.SomeClass // CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=extension.SomeClass -// CHECK-NEXT: {{^}} (decl version=51 unavailable=macOS decl=functionWithStmtConditionsInUnavailableExt() +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=functionWithStmtConditionsInUnavailableExt() // CHECK-NEXT: {{^}} (condition_following_availability version=52 unavailable=macOS // CHECK-NEXT: {{^}} (condition_following_availability version=53 unavailable=macOS // CHECK-NEXT: {{^}} (if_then version=53 unavailable=macOS // CHECK-NEXT: {{^}} (condition_following_availability version=54 unavailable=macOS // CHECK-NEXT: {{^}} (if_then version=54 unavailable=macOS // CHECK-NEXT: {{^}} (condition_following_availability version=55 unavailable=macOS -// CHECK-NEXT: {{^}} (decl version=55 unavailable=macOS decl=funcInGuardElse() +// CHECK-NEXT: {{^}} (decl version=54 unavailable=macOS decl=funcInGuardElse() // CHECK-NEXT: {{^}} (guard_fallthrough version=55 unavailable=macOS // CHECK-NEXT: {{^}} (condition_following_availability version=56 unavailable=macOS // CHECK-NEXT: {{^}} (guard_fallthrough version=56 unavailable=macOS -// CHECK-NEXT: {{^}} (decl version=57 unavailable=macOS decl=funcInInnerIfElse() -// CHECK-NEXT: {{^}} (decl version=53 unavailable=macOS decl=funcInOuterIfElse() +// CHECK-NEXT: {{^}} (decl version=53 unavailable=macOS decl=funcInInnerIfElse() +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=funcInOuterIfElse() @available(OSX, unavailable) extension SomeClass { @available(OSX 51, *) @@ -401,7 +401,7 @@ extension SomeEnum { // CHECK-NEXT: {{^}} (decl_implicit version=50 decl=extension.SomeEnum // CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=extension.SomeEnum // CHECK-NEXT: {{^}} (decl_implicit version=50 unavailable=macOS decl=availableMacOS_52 -// CHECK-NEXT: {{^}} (decl version=52 unavailable=macOS decl=availableMacOS_52 +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=availableMacOS_52 // CHECK-NEXT: {{^}} (decl version=50 unavailable=* decl=neverAvailable() @available(macOS, unavailable) @@ -418,10 +418,25 @@ extension SomeEnum { // CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=unavailableOnMacOSAndIntroduced() -@available(macOS, unavailable, introduced: 52) +@available(macOS, unavailable) +@available(macOS, introduced: 52) func unavailableOnMacOSAndIntroduced() { } +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=introducedOnMacOSAndUnavailable() + +@available(macOS, introduced: 53) +@available(macOS, unavailable) +func introducedOnMacOSAndUnavailable() { +} + + +// CHECK-NEXT: {{^}} (decl version=50 unavailable=macOS decl=unavailableOnMacOSAndIntroducedSameAttr() + +@available(macOS, unavailable, introduced: 54) +func unavailableOnMacOSAndIntroducedSameAttr() { +} + // CHECK-NEXT: {{^}} (decl version=50 unavailable=* decl=NeverAvailable // CHECK-NEXT: {{^}} (decl version=50 unavailable=* decl=unavailableOnMacOS() diff --git a/test/Sema/property_wrapper_availability.swift b/test/Sema/property_wrapper_availability.swift index daf3ab2771322..030be36469e15 100644 --- a/test/Sema/property_wrapper_availability.swift +++ b/test/Sema/property_wrapper_availability.swift @@ -99,7 +99,7 @@ struct UnavailableStruct { @UnavailableWrapper var unavailableInferred = S() @WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S - @WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 var wrappedValueAavailable51: S } @available(macOS, unavailable) @@ -117,7 +117,7 @@ struct UnavailableOnMacOSStruct { @UnavailableWrapper var unavailableInferred = S() @WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S - @WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 var wrappedValueAavailable51: S } func alwaysAvailableFunc( // expected-note 4 {{add @available attribute to enclosing global function}} @@ -160,14 +160,14 @@ func unavailableFunc( @DeprecatedWrapper _ deprecated: S, @UnavailableWrapper _ unavailable: S, @WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, - @WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 _ wrappedValueAavailable51: S ) { @AlwaysAvailableWrapper var alwaysAvailableLocal = S() @Available51Wrapper var available51Local = S() @DeprecatedWrapper var deprecatedLocal = S() @UnavailableWrapper var unavailableLocal = S() @WrappedValueUnavailableOnMacOS var unavailableWrappedValueLocal = S() - @WrappedValueAvailable51 var wrappedValueAavailable51 = S() // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 var wrappedValueAavailable51 = S() } @available(macOS, unavailable) @@ -177,12 +177,12 @@ func unavailableOnMacOSFunc( @DeprecatedWrapper _ deprecated: S, @UnavailableWrapper _ unavailable: S, @WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, - @WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 _ wrappedValueAavailable51: S ) { @AlwaysAvailableWrapper var alwaysAvailableLocal = S() @Available51Wrapper var available51Local = S() @DeprecatedWrapper var deprecatedLocal = S() @UnavailableWrapper var unavailableLocal = S() @WrappedValueUnavailableOnMacOS var unavailableWrappedValueLocal = S() - @WrappedValueAvailable51 var wrappedValueAavailable51 = S() // expected-error {{'wrappedValue' is only available in macOS 51 or newer}} + @WrappedValueAvailable51 var wrappedValueAavailable51 = S() } diff --git a/test/attr/attr_availability_transitive_osx.swift b/test/attr/attr_availability_transitive_osx.swift index b0a17ee2f3b93..7187ca6c26ea0 100644 --- a/test/attr/attr_availability_transitive_osx.swift +++ b/test/attr/attr_availability_transitive_osx.swift @@ -87,8 +87,7 @@ func never_available_func( ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -105,8 +104,7 @@ func osx_func( ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -159,7 +157,7 @@ var never_var: ( ) = ( always(), never(), // expected-error {{'never()' is unavailable}} - osx_future(), // expected-error {{'osx_future()' is only available in macOS 99 or newer}} + osx_future(), osx(), osx_ios(), osx_extension() @@ -176,7 +174,7 @@ var osx_var: ( ) = ( always(), never(), // expected-error {{'never()' is unavailable}} - osx_future(), // expected-error {{'osx_future()' is only available in macOS 99 or newer}} + osx_future(), osx(), osx_ios(), osx_extension() @@ -218,7 +216,7 @@ struct AlwaysAvailableContainer { // expected-note 2 {{add @available attribute struct NeverAvailableContainer { // expected-note 2 {{'NeverAvailableContainer' has been explicitly marked unavailable here}} let always_var: AlwaysAvailable = always() let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}} - let osx_future_var: OSXFutureAvailable = osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} + let osx_future_var: OSXFutureAvailable = osx_future() let osx_var: OSXUnavailable = osx() let osx_ios_var: MultiPlatformUnavailable = osx_ios() let osx_extension_var: OSXAppExtensionsUnavailable = osx_extension() @@ -228,7 +226,7 @@ struct NeverAvailableContainer { // expected-note 2 {{'NeverAvailableContainer' struct OSXUnavailableContainer { // expected-note 2 {{'OSXUnavailableContainer' has been explicitly marked unavailable here}} let always_var: AlwaysAvailable = always() let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}} - let osx_future_var: OSXFutureAvailable = osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} + let osx_future_var: OSXFutureAvailable = osx_future() let osx_var: OSXUnavailable = osx() let osx_ios_var: MultiPlatformUnavailable = osx_ios() let osx_extension_var: OSXAppExtensionsUnavailable = osx_extension() @@ -301,8 +299,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -319,8 +316,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -337,15 +333,14 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() } @available(OSXApplicationExtension, unavailable) - func never_available_extension_osx_app_extension_method( // expected-note {{add @available attribute to enclosing instance method}} + func never_available_extension_osx_app_extension_method( _: AlwaysAvailable, _: NeverAvailable, _: OSXFutureAvailable, @@ -355,8 +350,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -380,8 +374,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -398,8 +391,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -416,15 +408,14 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() } @available(OSXApplicationExtension, unavailable) - func osx_extension_osx_app_extension_method( // expected-note {{add @available attribute to enclosing instance method}} + func osx_extension_osx_app_extension_method( _: AlwaysAvailable, _: NeverAvailable, _: OSXFutureAvailable, @@ -434,8 +425,7 @@ extension ExtendMe { ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -477,8 +467,7 @@ extension ExtendMe { // expected-note * {{add @available attribute to enclosing ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -495,8 +484,7 @@ extension ExtendMe { // expected-note * {{add @available attribute to enclosing ) { always() never() // expected-error {{'never()' is unavailable}} - osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + osx_future() osx() osx_ios() osx_extension() @@ -534,7 +522,7 @@ func available_func_call_extension_methods(_ e: ExtendMe) { // expected-note {{a } @available(OSX, obsoleted: 10.9) -struct OSXObsoleted {} // expected-note 2 {{'OSXObsoleted' was obsoleted in macOS 10.9}} +struct OSXObsoleted {} // expected-note 4 {{'OSXObsoleted' was obsoleted in macOS 10.9}} @available(OSX, unavailable) @available(OSX, introduced: 99) @@ -561,17 +549,46 @@ func osx_unavailable_func( OSXUnavailableAndIntroducedInFutureSameAttribute, OSXIntroducedInFutureAndUnavailable ) { - // FIXME: [availability] Stop diagnosing potential unavailability or obsoletion in an unavailable context. - _ = OSXFutureAvailable() // expected-error {{'OSXFutureAvailable' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + // FIXME: [availability] Stop diagnosing obsoletion in an unavailable context. + _ = OSXFutureAvailable() _ = OSXObsoleted() // expected-error {{'OSXObsoleted' is unavailable in macOS}} _ = OSXUnavailableAndIntroducedInFuture() _ = OSXUnavailableAndIntroducedInFutureSameAttribute() _ = OSXIntroducedInFutureAndUnavailable() func takesType(_ t: T.Type) {} - takesType(OSXFutureAvailable.self) // expected-error {{'OSXFutureAvailable' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + takesType(OSXFutureAvailable.self) + takesType(OSXObsoleted.self) // expected-error {{'OSXObsoleted' is unavailable in macOS}} + takesType(OSXUnavailableAndIntroducedInFuture.self) + takesType(OSXUnavailableAndIntroducedInFutureSameAttribute.self) + takesType(OSXIntroducedInFutureAndUnavailable.self) + + return (s1, s2, s3, s4, s5) +} + +@available(OSX, unavailable, introduced: 99) +func osx_unavailable_and_introduced_func( + _ s1: OSXFutureAvailable, + _ s2: OSXObsoleted, + _ s3: OSXUnavailableAndIntroducedInFuture, + _ s4: OSXUnavailableAndIntroducedInFutureSameAttribute, + _ s5: OSXIntroducedInFutureAndUnavailable, +) -> ( + OSXFutureAvailable, + OSXObsoleted, + OSXUnavailableAndIntroducedInFuture, + OSXUnavailableAndIntroducedInFutureSameAttribute, + OSXIntroducedInFutureAndUnavailable +) { + // FIXME: [availability] Stop diagnosing obsoletion in an unavailable context. + _ = OSXFutureAvailable() + _ = OSXObsoleted() // expected-error {{'OSXObsoleted' is unavailable in macOS}} + _ = OSXUnavailableAndIntroducedInFuture() + _ = OSXUnavailableAndIntroducedInFutureSameAttribute() + _ = OSXIntroducedInFutureAndUnavailable() + + func takesType(_ t: T.Type) {} + takesType(OSXFutureAvailable.self) takesType(OSXObsoleted.self) // expected-error {{'OSXObsoleted' is unavailable in macOS}} takesType(OSXUnavailableAndIntroducedInFuture.self) takesType(OSXUnavailableAndIntroducedInFutureSameAttribute.self) diff --git a/test/attr/attr_availability_transitive_osx_appext.swift b/test/attr/attr_availability_transitive_osx_appext.swift index 412af439ffe15..371b90cbd5943 100644 --- a/test/attr/attr_availability_transitive_osx_appext.swift +++ b/test/attr/attr_availability_transitive_osx_appext.swift @@ -386,8 +386,7 @@ func osx_func_call_extension_methods(_ e: ExtendMe) { e.never_available_extension_osx_future_method() // expected-error {{'never_available_extension_osx_future_method()' is unavailable}} e.osx_extension_osx_future_method() - e.osx_app_extension_extension_osx_future_method() // expected-error {{'osx_app_extension_extension_osx_future_method()' is only available in macOS 99 or newer}} - // expected-note@-1 {{add 'if #available' version check}} + e.osx_app_extension_extension_osx_future_method() e.osx_app_extension_extension_never_available_method() // expected-error {{'osx_app_extension_extension_never_available_method()' is unavailable}} e.osx_app_extension_extension_osx_method() e.osx_app_extension_extension_osx_app_extension_method() diff --git a/test/attr/attr_inlinable_available.swift b/test/attr/attr_inlinable_available.swift index 1f948801dc06f..4b6cd0e875a75 100644 --- a/test/attr/attr_inlinable_available.swift +++ b/test/attr/attr_inlinable_available.swift @@ -321,14 +321,14 @@ public func alwaysUnavailable( ) { defer { _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() } _ = NoAvailable() _ = BeforeInliningTarget() _ = AtInliningTarget() _ = BetweenTargets() _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() _ = Unavailable() if #available(macOS 11, *) { @@ -568,14 +568,14 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri ) { defer { _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() } _ = NoAvailable() _ = BeforeInliningTarget() _ = AtInliningTarget() _ = BetweenTargets() _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() _ = Unavailable() if #available(macOS 11, *) { @@ -718,7 +718,7 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri _ = AtInliningTarget() _ = BetweenTargets() _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() if #available(macOS 11, *) { _ = AfterDeploymentTarget() @@ -727,7 +727,7 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri return () } -@inlinable public var inlinedNoAvailableGlobalUnavailableSetter: Any { // expected-note {{add @available attribute to enclosing var}} +@inlinable public var inlinedNoAvailableGlobalUnavailableSetter: Any { get { fatalError() } @@ -738,7 +738,7 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri _ = AtInliningTarget() _ = BetweenTargets() _ = AtDeploymentTarget() - _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}} + _ = AfterDeploymentTarget() if #available(macOS 11, *) { _ = AfterDeploymentTarget() @@ -847,7 +847,7 @@ public func defaultArgsUseUnavailable( _: Any = AtInliningTarget.self, _: Any = BetweenTargets.self, _: Any = AtDeploymentTarget.self, - _: Any = AfterDeploymentTarget.self, // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} + _: Any = AfterDeploymentTarget.self, _: Any = Unavailable.self ) {} @@ -909,7 +909,7 @@ public struct PropertyWrapper { public init(_ value: T) { self.wrappedValue = value } } -public struct PublicStruct { // expected-note 21 {{add @available attribute}} +public struct PublicStruct { // expected-note 20 {{add @available attribute}} // Public property declarations are exposed. public var aPublic: NoAvailable, bPublic: BeforeInliningTarget, @@ -961,7 +961,7 @@ public struct PublicStruct { // expected-note 21 {{add @available attribute}} @available(macOS, unavailable) public var fUnavailable: AfterDeploymentTarget { - AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available' version check}} + AfterDeploymentTarget() } // The inferred types of public properties are exposed. @@ -1167,7 +1167,7 @@ public struct UnavailablePublicStruct { cPublicInit: Any = AtInliningTarget(), dPublicInit: Any = BetweenTargets(), ePublicInit: Any = AtDeploymentTarget(), - fPublicInit: Any = AfterDeploymentTarget(), // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} + fPublicInit: Any = AfterDeploymentTarget(), gPublicInit: Any = Unavailable() var aInternal: NoAvailable = .init(),