@@ -315,6 +315,19 @@ ExportContext::getExportabilityReason() const {
315315 return std::nullopt ;
316316}
317317
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+
318331// / Returns the first availability attribute on the declaration that is active
319332// / on the target platform.
320333static const AvailableAttr *getActiveAvailableAttribute (const Decl *D,
@@ -3065,6 +3078,51 @@ bool diagnoseExplicitUnavailability(
30653078 return true ;
30663079}
30673080
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+
30683126// / Check if this is a subscript declaration inside String or
30693127// / Substring that returns String, and if so return true.
30703128bool isSubscriptReturningString (const ValueDecl *D, ASTContext &Context) {
@@ -4057,8 +4115,20 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
40574115 return false ;
40584116 }
40594117
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+ }
40624132
40634133 if (diagnoseDeclAsyncAvailability (D, R, call, Where))
40644134 return true ;
@@ -4079,25 +4149,21 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
40794149 return false ;
40804150
40814151 // Diagnose (and possibly signal) for potential unavailability
4082- auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, Where);
4083- if (!maybeUnavail.has_value ())
4152+ if (!requiredRange)
40844153 return false ;
40854154
4086- auto requiredAvailability = maybeUnavail.value ();
4087- auto *DC = Where.getDeclContext ();
4088- auto &ctx = DC->getASTContext ();
40894155 if (Flags.contains (
40904156 DeclAvailabilityFlag::
40914157 AllowPotentiallyUnavailableAtOrBelowDeploymentTarget) &&
4092- requiresDeploymentTargetOrEarlier (requiredAvailability , ctx))
4158+ requiresDeploymentTargetOrEarlier (*requiredRange , ctx))
40934159 return false ;
40944160
40954161 if (accessor) {
40964162 bool forInout = Flags.contains (DeclAvailabilityFlag::ForInout);
4097- diagnosePotentialAccessorUnavailability (accessor, R, DC,
4098- requiredAvailability, forInout);
4163+ diagnosePotentialAccessorUnavailability (accessor, R, DC, *requiredRange,
4164+ forInout);
40994165 } else {
4100- if (!diagnosePotentialUnavailability (D, R, DC, requiredAvailability ))
4166+ if (!diagnosePotentialUnavailability (D, R, DC, *requiredRange ))
41014167 return false ;
41024168 }
41034169
0 commit comments