From a288422a996b69367bcaa0f69c47d3d5be281f4c Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Mon, 19 Aug 2024 22:14:36 -0700 Subject: [PATCH] Sema: Fix override availability checking for protocols. Given the following test case, override availability checking produced an erroneus diagnostic: ``` @available(macOS 10.15, *) protocol P { associatedtype A var a: A { get set } } @available(macOS 13.0, *) protocol Q: P { // error: overriding _modify accessor for 'a' must be as available as // declaration it overrides var a: A { get set } } ``` The synthesized `_modify` accessor in `Q` is explicitly marked available in macOS 13, which is less available than the `_modify` accessor in `P`. The availability of `Q` should limit the required availability of the override and prevent the diagnostic, but the implementation had a bug where it checked the availability of the context's type instead of the contextual self type's declaration. In the example, the context's type is `Self` which does not have annotated availability. Resolves rdar://133573707. --- lib/Sema/TypeCheckDeclOverride.cpp | 6 ++--- test/Sema/availability_versions.swift | 38 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 5e7d6cabad8aa..40256cfd1db4d 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -1774,9 +1774,9 @@ static bool isAvailabilitySafeForOverride(ValueDecl *override, // Allow overrides that are not as available as the base decl as long as the // override is as available as its context. - auto overrideTypeAvailability = AvailabilityInference::inferForType( - override->getDeclContext()->getSelfTypeInContext()); - + auto overrideTypeAvailability = AvailabilityInference::availableRange( + override->getDeclContext()->getSelfNominalTypeDecl(), ctx); + return overrideTypeAvailability.isContainedIn(overrideInfo); } diff --git a/test/Sema/availability_versions.swift b/test/Sema/availability_versions.swift index 79cbbad4a4cf4..46d179f43890d 100644 --- a/test/Sema/availability_versions.swift +++ b/test/Sema/availability_versions.swift @@ -218,6 +218,44 @@ class SubClassOverridingPotentiallyUnavailableMethod : ClassWithPotentiallyUnava } } +protocol BaseProto { + associatedtype A + + var property: A { get set } // expected-note {{overridden declaration is here}} + + @available(OSX 10.51, *) + var newProperty: A { get set } // expected-note {{overridden declaration is here}} + + func method() // expected-note {{overridden declaration is here}} +} + +protocol RefinesBaseProto_AsAvailableOverrides: BaseProto { + var property: A { get set } + + @available(OSX 10.51, *) + var newProperty: A { get set } + + func method() +} + +protocol RefinesBaseProto_LessAvailableOverrides: BaseProto { + @available(OSX 10.52, *) + var property: A { get set } // expected-error {{overriding 'property' must be as available as declaration it overrides}} + + @available(OSX 10.52, *) + var newProperty: A { get set } // expected-error {{overriding 'newProperty' must be as available as declaration it overrides}} + + @available(OSX 10.52, *) + func method() // expected-error {{overriding 'method' must be as available as declaration it overrides}} +} + +@available(OSX 10.52, *) +protocol RefinesBaseProto_LessAvailable: BaseProto { + var property: A { get set } + var newProperty: A { get set } + func method() +} + class ClassWithPotentiallyUnavailableOverloadedMethod { @available(OSX, introduced: 10.9) func overloadedMethod() {}