Skip to content

Commit 3ad073d

Browse files
committed
AST/Sema: Retire SemanticAvailableAttr::getVersionAvailability().
Query for availability constraints instead of calling getVersionAvailability().
1 parent ac16d82 commit 3ad073d

File tree

7 files changed

+73
-110
lines changed

7 files changed

+73
-110
lines changed

include/swift/AST/Attr.h

-23
Original file line numberDiff line numberDiff line change
@@ -704,23 +704,6 @@ class SwiftNativeObjCRuntimeBaseAttr : public DeclAttribute {
704704
}
705705
};
706706

707-
/// Determine the result of comparing an availability attribute to a specific
708-
/// platform or language version.
709-
enum class AvailableVersionComparison {
710-
/// The entity is guaranteed to be available.
711-
Available,
712-
713-
/// The entity is never available.
714-
Unavailable,
715-
716-
/// The entity might be unavailable at runtime, because it was introduced
717-
/// after the requested minimum platform version.
718-
PotentiallyUnavailable,
719-
720-
/// The entity has been obsoleted.
721-
Obsoleted,
722-
};
723-
724707
/// Defines the @available attribute.
725708
class AvailableAttr : public DeclAttribute {
726709
public:
@@ -3395,12 +3378,6 @@ class SemanticAvailableAttr final {
33953378
/// version for PackageDescription version-specific availability.
33963379
llvm::VersionTuple getActiveVersion(const ASTContext &ctx) const;
33973380

3398-
/// Compare this attribute's version information against the platform or
3399-
/// language version (assuming the this attribute pertains to the active
3400-
/// platform).
3401-
AvailableVersionComparison
3402-
getVersionAvailability(const ASTContext &ctx) const;
3403-
34043381
/// Returns true if this attribute is considered active in the current
34053382
/// compilation context.
34063383
bool isActive(ASTContext &ctx) const;

lib/AST/Attr.cpp

-44
Original file line numberDiff line numberDiff line change
@@ -2309,50 +2309,6 @@ SemanticAvailableAttr::getActiveVersion(const ASTContext &ctx) const {
23092309
}
23102310
}
23112311

2312-
AvailableVersionComparison
2313-
SemanticAvailableAttr::getVersionAvailability(const ASTContext &ctx) const {
2314-
2315-
// Unconditional unavailability.
2316-
if (attr->isUnconditionallyUnavailable())
2317-
return AvailableVersionComparison::Unavailable;
2318-
2319-
llvm::VersionTuple queryVersion = getActiveVersion(ctx);
2320-
std::optional<llvm::VersionTuple> ObsoletedVersion = getObsoleted();
2321-
2322-
StringRef ObsoletedPlatform;
2323-
llvm::VersionTuple RemappedObsoletedVersion;
2324-
if (AvailabilityInference::updateObsoletedPlatformForFallback(
2325-
*this, ctx, ObsoletedPlatform, RemappedObsoletedVersion))
2326-
ObsoletedVersion = RemappedObsoletedVersion;
2327-
2328-
// If this entity was obsoleted before or at the query platform version,
2329-
// consider it obsolete.
2330-
if (ObsoletedVersion && *ObsoletedVersion <= queryVersion)
2331-
return AvailableVersionComparison::Obsoleted;
2332-
2333-
std::optional<llvm::VersionTuple> IntroducedVersion = getIntroduced();
2334-
StringRef IntroducedPlatform;
2335-
llvm::VersionTuple RemappedIntroducedVersion;
2336-
if (AvailabilityInference::updateIntroducedPlatformForFallback(
2337-
*this, ctx, IntroducedPlatform, RemappedIntroducedVersion))
2338-
IntroducedVersion = RemappedIntroducedVersion;
2339-
2340-
// If this entity was introduced after the query version and we're doing a
2341-
// platform comparison, true availability can only be determined dynamically;
2342-
// if we're doing a _language_ version check, the query version is a
2343-
// static requirement, so we treat "introduced later" as just plain
2344-
// unavailable.
2345-
if (IntroducedVersion && *IntroducedVersion > queryVersion) {
2346-
if (isSwiftLanguageModeSpecific() || isPackageDescriptionVersionSpecific())
2347-
return AvailableVersionComparison::Unavailable;
2348-
else
2349-
return AvailableVersionComparison::PotentiallyUnavailable;
2350-
}
2351-
2352-
// The entity is available.
2353-
return AvailableVersionComparison::Available;
2354-
}
2355-
23562312
SpecializeAttr::SpecializeAttr(SourceLoc atLoc, SourceRange range,
23572313
TrailingWhereClause *clause, bool exported,
23582314
SpecializationKind kind,

lib/Sema/TypeCheckAttr.cpp

+48-33
Original file line numberDiff line numberDiff line change
@@ -2417,27 +2417,6 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *parsedAttr) {
24172417
}
24182418
}
24192419

2420-
SourceLoc attrLoc = parsedAttr->getLocation();
2421-
auto versionAvailability = attr->getVersionAvailability(Ctx);
2422-
if (versionAvailability == AvailableVersionComparison::Obsoleted ||
2423-
versionAvailability == AvailableVersionComparison::Unavailable) {
2424-
if (auto cannotBeUnavailable =
2425-
TypeChecker::diagnosticIfDeclCannotBeUnavailable(D)) {
2426-
diagnose(attrLoc, cannotBeUnavailable.value());
2427-
return;
2428-
}
2429-
2430-
if (auto *PD = dyn_cast<ProtocolDecl>(DC)) {
2431-
if (auto *VD = dyn_cast<ValueDecl>(D)) {
2432-
if (VD->isProtocolRequirement() && !PD->isObjC()) {
2433-
diagnoseAndRemoveAttr(parsedAttr,
2434-
diag::unavailable_method_non_objc_protocol);
2435-
return;
2436-
}
2437-
}
2438-
}
2439-
}
2440-
24412420
// The remaining diagnostics are only for attributes with introduced versions
24422421
// for specific platforms.
24432422
if (!attr->isPlatformSpecific() || !attr->getIntroduced().has_value())
@@ -2486,18 +2465,6 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *parsedAttr) {
24862465
}
24872466
}
24882467
}
2489-
2490-
std::optional<Diagnostic> MaybeNotAllowed =
2491-
TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(D);
2492-
if (MaybeNotAllowed.has_value()) {
2493-
AvailabilityRange DeploymentRange =
2494-
AvailabilityRange::forDeploymentTarget(Ctx);
2495-
if (EnclosingAnnotatedRange.has_value())
2496-
DeploymentRange.intersectWith(*EnclosingAnnotatedRange);
2497-
2498-
if (!DeploymentRange.isContainedIn(AttrRange))
2499-
diagnose(attrLoc, MaybeNotAllowed.value());
2500-
}
25012468
}
25022469

25032470
static bool canDeclareSymbolName(StringRef symbol, ModuleDecl *fromModule) {
@@ -5003,6 +4970,54 @@ void AttributeChecker::checkAvailableAttrs(ArrayRef<AvailableAttr *> Attrs) {
50034970
diagnose(D->getLoc(), diag::spi_preferred_over_spi_available);
50044971
}
50054972
}
4973+
4974+
if (Ctx.LangOpts.DisableAvailabilityChecking)
4975+
return;
4976+
4977+
// Compute availability constraints for the decl, relative to its parent
4978+
// declaration or to the deployment target.
4979+
auto availabilityContext = AvailabilityContext::forDeploymentTarget(Ctx);
4980+
if (auto parent =
4981+
AvailabilityInference::parentDeclForInferredAvailability(D)) {
4982+
auto parentAvailability = TypeChecker::availabilityForDeclSignature(parent);
4983+
availabilityContext.constrainWithContext(parentAvailability, Ctx);
4984+
}
4985+
4986+
auto availabilityConstraint =
4987+
getAvailabilityConstraintsForDecl(D, availabilityContext)
4988+
.getPrimaryConstraint();
4989+
if (!availabilityConstraint)
4990+
return;
4991+
4992+
// If the decl is unavailable relative to its parent and it's not a
4993+
// declaration that is allowed to be unavailable, diagnose.
4994+
if (availabilityConstraint->isUnavailable()) {
4995+
auto attr = availabilityConstraint->getAttr();
4996+
if (auto diag = TypeChecker::diagnosticIfDeclCannotBeUnavailable(D)) {
4997+
diagnose(attr.getParsedAttr()->getLocation(), diag.value());
4998+
return;
4999+
}
5000+
5001+
if (auto *PD = dyn_cast<ProtocolDecl>(D->getDeclContext())) {
5002+
if (auto *VD = dyn_cast<ValueDecl>(D)) {
5003+
if (VD->isProtocolRequirement() && !PD->isObjC()) {
5004+
diagnoseAndRemoveAttr(
5005+
const_cast<AvailableAttr *>(attr.getParsedAttr()),
5006+
diag::unavailable_method_non_objc_protocol);
5007+
return;
5008+
}
5009+
}
5010+
}
5011+
}
5012+
5013+
// If the decl is potentially unavailable relative to its parent and it's
5014+
// not a declaration that is allowed to be potentially unavailable, diagnose.
5015+
if (availabilityConstraint->isPotentiallyAvailable()) {
5016+
auto attr = availabilityConstraint->getAttr();
5017+
if (auto diag =
5018+
TypeChecker::diagnosticIfDeclCannotBePotentiallyUnavailable(D))
5019+
diagnose(attr.getParsedAttr()->getLocation(), diag.value());
5020+
}
50065021
}
50075022

50085023
void AttributeChecker::checkBackDeployedAttrs(

lib/Sema/TypeCheckDeclOverride.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,21 @@ bool swift::isOverrideBasedOnType(const ValueDecl *decl, Type declTy,
245245

246246
static bool isUnavailableInAllVersions(ValueDecl *decl) {
247247
ASTContext &ctx = decl->getASTContext();
248-
auto attr = decl->getUnavailableAttr();
249-
if (!attr)
250-
return false;
251248

252-
if (attr->isUnconditionallyUnavailable())
253-
return true;
249+
auto deploymentContext = AvailabilityContext::forDeploymentTarget(ctx);
250+
auto constraints = getAvailabilityConstraintsForDecl(decl, deploymentContext);
251+
for (auto constraint : constraints) {
252+
switch (constraint.getReason()) {
253+
case AvailabilityConstraint::Reason::UnconditionallyUnavailable:
254+
case AvailabilityConstraint::Reason::IntroducedInLaterVersion:
255+
return true;
256+
case AvailabilityConstraint::Reason::Obsoleted:
257+
case AvailabilityConstraint::Reason::IntroducedInLaterDynamicVersion:
258+
break;
259+
}
260+
}
254261

255-
return attr->getVersionAvailability(ctx) ==
256-
AvailableVersionComparison::Unavailable;
262+
return false;
257263
}
258264

259265
/// Perform basic checking to determine whether a declaration can override a

test/Parse/invalid.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,5 @@ class C_50734<@NSApplicationMain T: AnyObject> {} // expected-error {{@NSApplica
140140
func f6_50734<@discardableResult T>(x: T) {} // expected-error {{'@discardableResult' attribute cannot be applied to this declaration}}
141141
enum E_50734<@indirect T> {} // expected-error {{'indirect' is a declaration modifier, not an attribute}} expected-error {{'indirect' modifier cannot be applied to this declaration}}
142142
protocol P {
143-
@available(swift, introduced: 4) associatedtype Assoc
143+
@available(macOS, introduced: 10.9) associatedtype Assoc
144144
}

test/decl/protocol/associated_type_availability.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@ protocol P3 {
8989
@available(macOS, obsoleted: 12) // expected-error{{associated type cannot be marked unavailable with '@available'}}
9090
associatedtype A1
9191

92-
@available(macOS, obsoleted: 99) // FIXME: this should probably be diagnosed
92+
@available(macOS, obsoleted: 99)
9393
associatedtype A2
9494
}

test/decl/protocol/req/unavailable.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ protocol UnavailableAssoc {
104104
@available(*, unavailable) // expected-error {{associated type cannot be marked unavailable with '@available'}}
105105
associatedtype A1
106106

107-
@available(swift, introduced: 99) // expected-error {{associated type cannot be marked unavailable with '@available'}}
107+
@available(swift, introduced: 4)
108108
associatedtype A2
109+
110+
@available(swift, introduced: 99) // expected-error {{associated type cannot be marked unavailable with '@available'}}
111+
associatedtype A3
112+
113+
@available(swift, obsoleted: 4) // expected-error {{associated type cannot be marked unavailable with '@available'}}
114+
associatedtype A4
115+
116+
@available(swift, obsoleted: 99)
117+
associatedtype A5
109118
}

0 commit comments

Comments
 (0)