Skip to content

Commit e545826

Browse files
authored
Merge pull request #62327 from tshortli/swiftui-any-color-box-availability-exception
Sema: Allow `AnyColorBox` in SwiftUI to derive from a less available base class
2 parents 7b45c8b + 04b37ab commit e545826

File tree

7 files changed

+51
-26
lines changed

7 files changed

+51
-26
lines changed

include/swift/AST/Availability.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ class UnavailabilityReason {
208208
const VersionRange &getRequiredOSVersionRange() const {
209209
return RequiredDeploymentRange;
210210
}
211+
212+
/// Returns true if the required OS version range's lower endpoint is at or
213+
/// below the deployment target of the given ASTContext.
214+
bool requiresDeploymentTargetOrEarlier(ASTContext &Ctx) const;
211215
};
212216

213217
/// Represents everything that a particular chunk of code may assume about its

lib/AST/Availability.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ bool Decl::isSemanticallyUnavailable() const {
230230
return evaluateOrDefault(eval, IsSemanticallyUnavailableRequest{this}, false);
231231
}
232232

233+
bool UnavailabilityReason::requiresDeploymentTargetOrEarlier(
234+
ASTContext &Ctx) const {
235+
return RequiredDeploymentRange.getLowerEndpoint() <=
236+
AvailabilityContext::forDeploymentTarget(Ctx)
237+
.getOSVersion()
238+
.getLowerEndpoint();
239+
}
240+
233241
AvailabilityContext
234242
AvailabilityInference::annotatedAvailableRangeForAttr(const SpecializeAttr* attr,
235243
ASTContext &ctx) {

lib/Sema/TypeCheckAccess.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,15 +1887,17 @@ class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
18871887
DeclAvailabilityFlags flags =
18881888
DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
18891889

1890-
// As a concession to source compatibility for API libraries, downgrade
1891-
// diagnostics about inheritance from a less available type when the
1892-
// following conditions are met:
1893-
// 1. The inherited type is only potentially unavailable before the
1894-
// deployment target.
1895-
// 2. The inheriting type is `@usableFromInline`.
1896-
if (nominal->getAttrs().hasAttribute<UsableFromInlineAttr>())
1890+
// Allow the `AnyColorBox` class in SwiftUI to inherit from a less available
1891+
// super class as a one-off source compatibility exception. Availability
1892+
// checking generally doesn't support a more available class deriving from
1893+
// a less available base class in a library evolution enabled module, even
1894+
// when the base class is available at the deployment target, but this
1895+
// declaration slipped in when the compiler wasn't able to diagnose it and
1896+
// can't be changed.
1897+
if (nominal->getName().is("AnyColorBox") &&
1898+
nominal->getModuleContext()->getName().is("SwiftUI"))
18971899
flags |= DeclAvailabilityFlag::
1898-
WarnForPotentialUnavailabilityBeforeDeploymentTarget;
1900+
AllowPotentiallyUnavailableAtOrBelowDeploymentTarget;
18991901

19001902
llvm::for_each(nominal->getInherited(), [&](TypeLoc inherited) {
19011903
checkType(inherited.getType(), inherited.getTypeRepr(), nominal,

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,9 +2067,7 @@ static Diagnostic getPotentialUnavailabilityDiagnostic(
20672067
auto Platform = prettyPlatformString(targetPlatform(Context.LangOpts));
20682068
auto Version = Reason.getRequiredOSVersionRange().getLowerEndpoint();
20692069

2070-
if (Version <= AvailabilityContext::forDeploymentTarget(Context)
2071-
.getOSVersion()
2072-
.getLowerEndpoint()) {
2070+
if (Reason.requiresDeploymentTargetOrEarlier(Context)) {
20732071
// The required OS version is at or before the deployment target so this
20742072
// diagnostic should indicate that the decl could be unavailable to clients
20752073
// of the module containing the reference.
@@ -2090,7 +2088,7 @@ bool TypeChecker::diagnosePotentialUnavailability(
20902088
const ValueDecl *D, SourceRange ReferenceRange,
20912089
const DeclContext *ReferenceDC,
20922090
const UnavailabilityReason &Reason,
2093-
bool WarnBeforeDeploymentTarget) {
2091+
bool WarnBeforeDeploymentTarget = false) {
20942092
ASTContext &Context = ReferenceDC->getASTContext();
20952093

20962094
auto RequiredRange = Reason.getRequiredOSVersionRange();
@@ -3724,18 +3722,20 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
37243722
if (!maybeUnavail.has_value())
37253723
return false;
37263724

3725+
auto unavailReason = maybeUnavail.value();
37273726
auto *DC = Where.getDeclContext();
3727+
if (Flags.contains(
3728+
DeclAvailabilityFlag::
3729+
AllowPotentiallyUnavailableAtOrBelowDeploymentTarget) &&
3730+
unavailReason.requiresDeploymentTargetOrEarlier(DC->getASTContext()))
3731+
return false;
37283732

37293733
if (accessor) {
37303734
bool forInout = Flags.contains(DeclAvailabilityFlag::ForInout);
37313735
TypeChecker::diagnosePotentialAccessorUnavailability(
3732-
accessor, R, DC, maybeUnavail.value(), forInout);
3736+
accessor, R, DC, unavailReason, forInout);
37333737
} else {
3734-
bool downgradeBeforeDeploymentTarget = Flags.contains(
3735-
DeclAvailabilityFlag::
3736-
WarnForPotentialUnavailabilityBeforeDeploymentTarget);
3737-
if (!TypeChecker::diagnosePotentialUnavailability(
3738-
D, R, DC, maybeUnavail.value(), downgradeBeforeDeploymentTarget))
3738+
if (!TypeChecker::diagnosePotentialUnavailability(D, R, DC, unavailReason))
37393739
return false;
37403740
}
37413741

lib/Sema/TypeCheckAvailability.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,9 @@ enum class DeclAvailabilityFlag : uint8_t {
5858
/// warning. Used for ObjC key path components.
5959
ForObjCKeyPath = 1 << 3,
6060

61-
/// Downgrade errors about decl availability to warnings when the fix would be
62-
/// to constrain availability to a version that is more available than the
63-
/// current deployment target. This is needed for source compatibility in when
64-
/// checking public extensions in library modules.
65-
WarnForPotentialUnavailabilityBeforeDeploymentTarget = 1 << 4,
61+
/// Do not diagnose potential decl unavailability if that unavailability
62+
/// would only occur at or below the deployment target.
63+
AllowPotentiallyUnavailableAtOrBelowDeploymentTarget = 1 << 4,
6664
};
6765
using DeclAvailabilityFlags = OptionSet<DeclAvailabilityFlag>;
6866

test/Sema/availability_swiftui.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -verify -target %target-cpu-apple-macosx12.0 -module-name SwiftUI -library-level api
2+
// RUN: not %target-typecheck-verify-swift -verify -target %target-cpu-apple-macosx12.0 -module-name Other -library-level api
3+
4+
// REQUIRES: OS=macosx
5+
6+
@available(macOS 11, *)
7+
public class LessAvailable {}
8+
9+
@available(macOS 10.15, *)
10+
@usableFromInline
11+
class AnyColorBox: LessAvailable {} // Ok, exception specifically for AnyColorBox
12+
13+
@available(macOS 10.15, *)
14+
@usableFromInline
15+
class OtherClass: LessAvailable {} // expected-error {{'LessAvailable' is only available in macOS 11 or newer; clients of 'SwiftUI' may have a lower deployment target}}

test/attr/attr_inlinable_available.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,10 +1369,8 @@ public enum NoAvailableEnumWithClasses {
13691369
public class InheritsAtDeploymentTarget: AtDeploymentTargetClass {} // expected-error {{'AtDeploymentTargetClass' is only available in macOS 10.15 or newer; clients of 'Test' may have a lower deployment target}} expected-note 2 {{add @available attribute to enclosing class}}
13701370
public class InheritsAfterDeploymentTarget: AfterDeploymentTargetClass {} // expected-error {{'AfterDeploymentTargetClass' is only available in macOS 11 or newer}} expected-note 2 {{add @available attribute to enclosing class}}
13711371

1372-
// As a special case, downgrade the less available superclasses diagnostic for
1373-
// `@usableFromInline` classes.
13741372
@usableFromInline
1375-
class UFIInheritsBetweenTargets: BetweenTargetsClass {} // expected-warning {{'BetweenTargetsClass' is only available in macOS 10.14.5 or newer; clients of 'Test' may have a lower deployment target}} expected-note 2 {{add @available attribute to enclosing class}}
1373+
class UFIInheritsBetweenTargets: BetweenTargetsClass {} // expected-error {{'BetweenTargetsClass' is only available in macOS 10.14.5 or newer; clients of 'Test' may have a lower deployment target}} expected-note 2 {{add @available attribute to enclosing class}}
13761374
}
13771375

13781376
@_spi(Private)

0 commit comments

Comments
 (0)