@@ -315,6 +315,19 @@ ExportContext::getExportabilityReason() const {
315
315
return std::nullopt;
316
316
}
317
317
318
+ std::optional<AvailabilityRange>
319
+ UnmetAvailabilityRequirement::getRequiredNewerAvailabilityRange (
320
+ ASTContext &ctx) const {
321
+ switch (kind) {
322
+ case Kind::AlwaysUnavailable:
323
+ case Kind::RequiresVersion:
324
+ case Kind::Obsoleted:
325
+ return std::nullopt;
326
+ case Kind::IntroducedInNewerVersion:
327
+ return AvailabilityInference::availableRange (attr, ctx);
328
+ }
329
+ }
330
+
318
331
// / Returns the first availability attribute on the declaration that is active
319
332
// / on the target platform.
320
333
static const AvailableAttr *getActiveAvailableAttribute (const Decl *D,
@@ -3065,6 +3078,51 @@ bool diagnoseExplicitUnavailability(
3065
3078
return true ;
3066
3079
}
3067
3080
3081
+ std::optional<UnmetAvailabilityRequirement>
3082
+ swift::checkDeclarationAvailability (const Decl *decl,
3083
+ const DeclContext *declContext,
3084
+ AvailabilityContext availabilityContext) {
3085
+ auto &ctx = declContext->getASTContext ();
3086
+ if (ctx.LangOpts .DisableAvailabilityChecking )
3087
+ return std::nullopt;
3088
+
3089
+ // Generic parameters are always available.
3090
+ if (isa<GenericTypeParamDecl>(decl))
3091
+ return std::nullopt;
3092
+
3093
+ if (auto attr = AvailableAttr::isUnavailable (decl)) {
3094
+ if (isInsideCompatibleUnavailableDeclaration (decl, availabilityContext,
3095
+ attr))
3096
+ return std::nullopt;
3097
+
3098
+ switch (attr->getVersionAvailability (ctx)) {
3099
+ case AvailableVersionComparison::Available:
3100
+ case AvailableVersionComparison::PotentiallyUnavailable:
3101
+ llvm_unreachable (" Decl should be unavailable" );
3102
+
3103
+ case AvailableVersionComparison::Unavailable:
3104
+ if ((attr->isLanguageVersionSpecific () ||
3105
+ attr->isPackageDescriptionVersionSpecific ()) &&
3106
+ attr->Introduced .has_value ())
3107
+ return UnmetAvailabilityRequirement::forRequiresVersion (attr);
3108
+
3109
+ return UnmetAvailabilityRequirement::forAlwaysUnavailable (attr);
3110
+
3111
+ case AvailableVersionComparison::Obsoleted:
3112
+ return UnmetAvailabilityRequirement::forObsoleted (attr);
3113
+ }
3114
+ }
3115
+
3116
+ // Check whether the declaration is available in a newer platform version.
3117
+ auto rangeAndAttr = AvailabilityInference::availableRangeAndAttr (decl);
3118
+ if (!availabilityContext.getPlatformRange ().isContainedIn (rangeAndAttr.first ))
3119
+ return UnmetAvailabilityRequirement::forIntroducedInNewerVersion (
3120
+ rangeAndAttr.second );
3121
+
3122
+ return std::nullopt;
3123
+ }
3124
+
3125
+
3068
3126
// / Check if this is a subscript declaration inside String or
3069
3127
// / Substring that returns String, and if so return true.
3070
3128
bool isSubscriptReturningString (const ValueDecl *D, ASTContext &Context) {
@@ -4057,8 +4115,20 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
4057
4115
return false ;
4058
4116
}
4059
4117
4060
- if (diagnoseExplicitUnavailability (D, R, Where, call, Flags))
4061
- return true ;
4118
+ auto *DC = Where.getDeclContext ();
4119
+ auto &ctx = DC->getASTContext ();
4120
+ auto unmetRequirement =
4121
+ checkDeclarationAvailability (D, DC, Where.getAvailability ());
4122
+ auto requiredRange =
4123
+ unmetRequirement
4124
+ ? unmetRequirement->getRequiredNewerAvailabilityRange (ctx)
4125
+ : std::nullopt;
4126
+
4127
+ if (unmetRequirement && !requiredRange) {
4128
+ // FIXME: diagnoseExplicitUnavailability should take an unmet requirement
4129
+ if (diagnoseExplicitUnavailability (D, R, Where, call, Flags))
4130
+ return true ;
4131
+ }
4062
4132
4063
4133
if (diagnoseDeclAsyncAvailability (D, R, call, Where))
4064
4134
return true ;
@@ -4079,25 +4149,21 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
4079
4149
return false ;
4080
4150
4081
4151
// Diagnose (and possibly signal) for potential unavailability
4082
- auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, Where);
4083
- if (!maybeUnavail.has_value ())
4152
+ if (!requiredRange)
4084
4153
return false ;
4085
4154
4086
- auto requiredAvailability = maybeUnavail.value ();
4087
- auto *DC = Where.getDeclContext ();
4088
- auto &ctx = DC->getASTContext ();
4089
4155
if (Flags.contains (
4090
4156
DeclAvailabilityFlag::
4091
4157
AllowPotentiallyUnavailableAtOrBelowDeploymentTarget) &&
4092
- requiresDeploymentTargetOrEarlier (requiredAvailability , ctx))
4158
+ requiresDeploymentTargetOrEarlier (*requiredRange , ctx))
4093
4159
return false ;
4094
4160
4095
4161
if (accessor) {
4096
4162
bool forInout = Flags.contains (DeclAvailabilityFlag::ForInout);
4097
- diagnosePotentialAccessorUnavailability (accessor, R, DC,
4098
- requiredAvailability, forInout);
4163
+ diagnosePotentialAccessorUnavailability (accessor, R, DC, *requiredRange,
4164
+ forInout);
4099
4165
} else {
4100
- if (!diagnosePotentialUnavailability (D, R, DC, requiredAvailability ))
4166
+ if (!diagnosePotentialUnavailability (D, R, DC, *requiredRange ))
4101
4167
return false ;
4102
4168
}
4103
4169
0 commit comments