@@ -316,19 +316,6 @@ ExportContext::getExportabilityReason() const {
316316 return std::nullopt ;
317317}
318318
319- std::optional<AvailabilityRange>
320- UnmetAvailabilityRequirement::getRequiredNewerAvailabilityRange (
321- ASTContext &ctx) const {
322- switch (kind) {
323- case Kind::AlwaysUnavailable:
324- case Kind::RequiresVersion:
325- case Kind::Obsoleted:
326- return std::nullopt ;
327- case Kind::IntroducedInNewerVersion:
328- return AvailabilityInference::availableRange (attr, ctx);
329- }
330- }
331-
332319// / Returns the first availability attribute on the declaration that is active
333320// / on the target platform.
334321static const AvailableAttr *getActiveAvailableAttribute (const Decl *D,
@@ -1478,62 +1465,6 @@ AvailabilityRange TypeChecker::overApproximateAvailabilityAtLocation(
14781465 return availabilityAtLocation (loc, DC, MostRefined).getPlatformRange ();
14791466}
14801467
1481- bool TypeChecker::isDeclarationUnavailable (
1482- const Decl *D, const DeclContext *referenceDC,
1483- llvm::function_ref<AvailabilityRange()> getAvailabilityRange) {
1484- ASTContext &Context = referenceDC->getASTContext ();
1485- if (Context.LangOpts .DisableAvailabilityChecking ) {
1486- return false ;
1487- }
1488-
1489- if (!referenceDC->getParentSourceFile ()) {
1490- // We only check availability if this reference is in a source file; we do
1491- // not check in other kinds of FileUnits.
1492- return false ;
1493- }
1494-
1495- AvailabilityRange safeRangeUnderApprox{
1496- AvailabilityInference::availableRange (D)};
1497-
1498- if (safeRangeUnderApprox.isAlwaysAvailable ())
1499- return false ;
1500-
1501- AvailabilityRange runningOSOverApprox = getAvailabilityRange ();
1502-
1503- // The reference is safe if an over-approximation of the running OS
1504- // versions is fully contained within an under-approximation
1505- // of the versions on which the declaration is available. If this
1506- // containment cannot be guaranteed, we say the reference is
1507- // not available.
1508- return !runningOSOverApprox.isContainedIn (safeRangeUnderApprox);
1509- }
1510-
1511- std::optional<AvailabilityRange>
1512- TypeChecker::checkDeclarationAvailability (const Decl *D,
1513- const ExportContext &Where) {
1514- // Skip computing potential unavailability if the declaration is explicitly
1515- // unavailable and the context is also unavailable.
1516- if (const AvailableAttr *Attr = AvailableAttr::isUnavailable (D))
1517- if (isInsideCompatibleUnavailableDeclaration (D, Where.getAvailability (),
1518- Attr))
1519- return std::nullopt ;
1520-
1521- if (isDeclarationUnavailable (D, Where.getDeclContext (), [&Where] {
1522- return Where.getAvailabilityRange ();
1523- })) {
1524- return AvailabilityInference::availableRange (D);
1525- }
1526-
1527- return std::nullopt ;
1528- }
1529-
1530- std::optional<AvailabilityRange>
1531- TypeChecker::checkConformanceAvailability (const RootProtocolConformance *conf,
1532- const ExtensionDecl *ext,
1533- const ExportContext &where) {
1534- return checkDeclarationAvailability (ext, where);
1535- }
1536-
15371468// / A class that walks the AST to find the innermost (i.e., deepest) node that
15381469// / contains a target SourceRange and matches a particular criterion.
15391470// / This class finds the innermost nodes of interest by walking
@@ -2275,12 +2206,14 @@ behaviorLimitForExplicitUnavailability(
22752206
22762207// / Emits a diagnostic for a protocol conformance that is potentially
22772208// / unavailable at the given source location.
2278- static void
2209+ static bool
22792210diagnosePotentialUnavailability (const RootProtocolConformance *rootConf,
22802211 const ExtensionDecl *ext, SourceLoc loc,
22812212 const DeclContext *dc,
22822213 const AvailabilityRange &availability) {
22832214 ASTContext &ctx = dc->getASTContext ();
2215+ if (ctx.LangOpts .DisableAvailabilityChecking )
2216+ return false ;
22842217
22852218 {
22862219 auto type = rootConf->getType ();
@@ -2296,10 +2229,11 @@ diagnosePotentialUnavailability(const RootProtocolConformance *rootConf,
22962229 // Direct a fixit to the error if an existing guard is nearly-correct
22972230 if (fixAvailabilityByNarrowingNearbyVersionCheck (loc, dc, availability, ctx,
22982231 err))
2299- return ;
2232+ return true ;
23002233 }
23012234
23022235 fixAvailability (loc, dc, availability, ctx);
2236+ return true ;
23032237}
23042238
23052239// / Returns the availability attribute indicating deprecation of the
@@ -3099,9 +3033,9 @@ bool diagnoseExplicitUnavailability(
30993033}
31003034
31013035std::optional<UnmetAvailabilityRequirement>
3102- swift::checkDeclarationAvailability ( const Decl *decl,
3103- const DeclContext *declContext,
3104- AvailabilityContext availabilityContext) {
3036+ swift::getUnmetDeclAvailabilityRequirement (
3037+ const Decl *decl, const DeclContext *declContext,
3038+ AvailabilityContext availabilityContext) {
31053039 auto &ctx = declContext->getASTContext ();
31063040
31073041 // Generic parameters are always available.
@@ -3140,6 +3074,14 @@ swift::checkDeclarationAvailability(const Decl *decl,
31403074 return std::nullopt ;
31413075}
31423076
3077+ std::optional<UnmetAvailabilityRequirement>
3078+ swift::getUnmetDeclAvailabilityRequirement (const Decl *decl,
3079+ const DeclContext *referenceDC,
3080+ SourceLoc referenceLoc) {
3081+ return getUnmetDeclAvailabilityRequirement (
3082+ decl, referenceDC,
3083+ TypeChecker::availabilityAtLocation (referenceLoc, referenceDC));
3084+ }
31433085
31443086// / Check if this is a subscript declaration inside String or
31453087// / Substring that returns String, and if so return true.
@@ -4153,13 +4095,9 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
41534095 auto &ctx = DC->getASTContext ();
41544096
41554097 auto unmetRequirement =
4156- checkDeclarationAvailability (D, DC, Where.getAvailability ());
4157- auto requiredRange =
4158- unmetRequirement
4159- ? unmetRequirement->getRequiredNewerAvailabilityRange (ctx)
4160- : std::nullopt ;
4098+ getUnmetDeclAvailabilityRequirement (D, DC, Where.getAvailability ());
41614099
4162- if (unmetRequirement && !requiredRange ) {
4100+ if (unmetRequirement && !unmetRequirement-> isConditionallySatisfiable () ) {
41634101 // FIXME: diagnoseExplicitUnavailability should take an unmet requirement
41644102 if (diagnoseExplicitUnavailability (D, R, Where, call, Flags))
41654103 return true ;
@@ -4183,6 +4121,11 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
41834121 && isa<ProtocolDecl>(D))
41844122 return false ;
41854123
4124+ if (!unmetRequirement)
4125+ return false ;
4126+
4127+ auto requiredRange = unmetRequirement->getRequiredNewerAvailabilityRange (ctx);
4128+
41864129 // Diagnose (and possibly signal) for potential unavailability
41874130 if (!requiredRange)
41884131 return false ;
@@ -4630,6 +4573,7 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
46304573 // Diagnose "missing" conformances where we needed a conformance but
46314574 // didn't have one.
46324575 auto *DC = where.getDeclContext ();
4576+ auto &ctx = DC->getASTContext ();
46334577 if (auto builtinConformance = dyn_cast<BuiltinProtocolConformance>(rootConf)){
46344578 if (builtinConformance->isMissing ()) {
46354579 diagnoseMissingConformance (loc, builtinConformance->getType (),
@@ -4643,7 +4587,6 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
46434587
46444588 Type selfTy = rootConf->getProtocol ()->getSelfInterfaceType ();
46454589 if (!depTy->isEqual (selfTy)) {
4646- auto &ctx = DC->getASTContext ();
46474590 ctx.Diags .diagnose (
46484591 loc,
46494592 diag::assoc_conformance_from_implementation_only_module,
@@ -4658,20 +4601,26 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
46584601 return true ;
46594602 }
46604603
4661- if (diagnoseExplicitUnavailability (loc, rootConf, ext, where,
4662- warnIfConformanceUnavailablePreSwift6)) {
4663- maybeEmitAssociatedTypeNote ();
4664- return true ;
4665- }
4604+ auto unmetRequirement = getUnmetDeclAvailabilityRequirement (
4605+ ext, where.getDeclContext (), where.getAvailability ());
4606+ if (unmetRequirement) {
4607+ // FIXME: diagnoseExplicitUnavailability() should take unmet requirement
4608+ if (diagnoseExplicitUnavailability (
4609+ loc, rootConf, ext, where,
4610+ warnIfConformanceUnavailablePreSwift6)) {
4611+ maybeEmitAssociatedTypeNote ();
4612+ return true ;
4613+ }
46664614
4667- // Diagnose (and possibly signal) for potential unavailability
4668- auto maybeUnavail = TypeChecker::checkConformanceAvailability (
4669- rootConf, ext, where);
4670- if (maybeUnavail.has_value ()) {
4671- diagnosePotentialUnavailability (rootConf, ext, loc, DC,
4672- maybeUnavail.value ());
4673- maybeEmitAssociatedTypeNote ();
4674- return true ;
4615+ // Diagnose (and possibly signal) for potential unavailability
4616+ if (auto requiredRange =
4617+ unmetRequirement->getRequiredNewerAvailabilityRange (ctx)) {
4618+ if (diagnosePotentialUnavailability (rootConf, ext, loc, DC,
4619+ *requiredRange)) {
4620+ maybeEmitAssociatedTypeNote ();
4621+ return true ;
4622+ }
4623+ }
46754624 }
46764625
46774626 // Diagnose for deprecation
0 commit comments