Skip to content

Commit bd7a394

Browse files
committed
Sema: Allow explicitly available overrides to be as available as their context.
Previously, the following test case produced an erroneous diagnostic: ``` class A { init() {} } @available(macOS 12, *) class B: A { @available(macOS 12, *) override init() { // error: overriding 'init' must be as available as declaration it overrides super.init() } } ``` The overridden `init()` constructor is as available as it can possibly be. Removing the explicit `@available` annotation suppressed the diagnostic. To fix this, we check to see if the override is as available as its self type and accept it if it is. You may be wondering how this works when the `@available` annotation is removed from `override init()` in the example. It turns out that `AvailabilityInference::availableRange()` returns a result that is based only on the explicit availability of the decl in question without taking the availability of the context into account (except when the context is an extension). So with the explicit annotation gone, both the base `init()` and the override are both considered to be "always" available. This is pretty unintuitive and arguably wrong. However, it seems like a lot of existing code depends on this behavior so I've left it for now. Resolves rdar://96253347
1 parent f1207ff commit bd7a394

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,15 @@ static bool isAvailabilitySafeForOverride(ValueDecl *override,
17141714
AvailabilityContext baseInfo =
17151715
AvailabilityInference::availableRange(base, ctx);
17161716

1717-
return baseInfo.isContainedIn(overrideInfo);
1717+
if (baseInfo.isContainedIn(overrideInfo))
1718+
return true;
1719+
1720+
// Allow overrides that are not as available as the base decl as long as the
1721+
// override is as available as its context.
1722+
auto overrideTypeAvailability = AvailabilityInference::inferForType(
1723+
override->getDeclContext()->getSelfTypeInContext());
1724+
1725+
return overrideTypeAvailability.isContainedIn(overrideInfo);
17181726
}
17191727

17201728
/// Returns true if a diagnostic about an accessor being less available

test/Sema/availability_versions.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,26 @@ class SubWithLimitedMemberAvailability : SuperWithAlwaysAvailableMembers {
839839
}
840840
}
841841

842+
@available(OSX, introduced: 10.51)
843+
class SubWithLimitedAvailablility : SuperWithAlwaysAvailableMembers {
844+
override func shouldAlwaysBeAvailableMethod() {}
845+
846+
override var shouldAlwaysBeAvailableProperty: Int {
847+
get { return 10 }
848+
set(newVal) {}
849+
}
850+
851+
override var setterShouldAlwaysBeAvailableProperty: Int {
852+
get { return 9 }
853+
set(newVal) {}
854+
}
855+
856+
override var getterShouldAlwaysBeAvailableProperty: Int {
857+
get { return 9 }
858+
set(newVal) {}
859+
}
860+
}
861+
842862
class SuperWithLimitedMemberAvailability {
843863
@available(OSX, introduced: 10.51)
844864
func someMethod() {
@@ -879,6 +899,44 @@ class SubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability {
879899
}
880900
}
881901

902+
@available(OSX, introduced: 10.51)
903+
class SubWithLimitedAvailability : SuperWithLimitedMemberAvailability {
904+
override func someMethod() {
905+
super.someMethod()
906+
}
907+
908+
override var someProperty: Int {
909+
get { super.someProperty }
910+
set(newVal) { super.someProperty = newVal }
911+
}
912+
}
913+
914+
@available(OSX, introduced: 10.52)
915+
class SubWithMoreLimitedAvailability : SuperWithLimitedMemberAvailability {
916+
override func someMethod() {
917+
super.someMethod()
918+
}
919+
920+
override var someProperty: Int {
921+
get { super.someProperty }
922+
set(newVal) { super.someProperty = newVal }
923+
}
924+
}
925+
926+
@available(OSX, introduced: 10.52)
927+
class SubWithMoreLimitedAvailabilityAndRedundantMemberAvailability : SuperWithLimitedMemberAvailability {
928+
@available(OSX, introduced: 10.52)
929+
override func someMethod() {
930+
super.someMethod()
931+
}
932+
933+
@available(OSX, introduced: 10.52)
934+
override var someProperty: Int {
935+
get { super.someProperty }
936+
set(newVal) { super.someProperty = newVal }
937+
}
938+
}
939+
882940
@available(OSX, unavailable)
883941
class UnavailableSubWithLargerMemberAvailability : SuperWithLimitedMemberAvailability {
884942
override func someMethod() {

0 commit comments

Comments
 (0)