@@ -215,15 +215,20 @@ computeExportContextBits(ASTContext &Ctx, Decl *D, bool *spi, bool *implicit,
215
215
}
216
216
}
217
217
218
+ static AvailabilityContext availabilityAtLocation (SourceLoc loc,
219
+ const DeclContext *dc) {
220
+ auto &ctx = dc->getASTContext ();
221
+ return ctx.LangOpts .DisableAvailabilityChecking
222
+ ? AvailabilityContext::alwaysAvailable ()
223
+ : TypeChecker::overApproximateAvailabilityAtLocation (loc, dc);
224
+ }
225
+
218
226
ExportContext ExportContext::forDeclSignature (Decl *D) {
219
227
auto &Ctx = D->getASTContext ();
220
228
221
229
auto *DC = D->getInnermostDeclContext ();
222
230
auto fragileKind = DC->getFragileFunctionKind ();
223
- auto runningOSVersion =
224
- (Ctx.LangOpts .DisableAvailabilityChecking
225
- ? AvailabilityContext::alwaysAvailable ()
226
- : TypeChecker::overApproximateAvailabilityAtLocation (D->getLoc (), DC));
231
+ auto runningOSVersion = availabilityAtLocation (D->getLoc (), DC);
227
232
bool spi = Ctx.LangOpts .LibraryLevel == LibraryLevel::SPI;
228
233
bool implicit = false ;
229
234
bool deprecated = false ;
@@ -248,11 +253,7 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
248
253
auto &Ctx = DC->getASTContext ();
249
254
250
255
auto fragileKind = DC->getFragileFunctionKind ();
251
- auto runningOSVersion =
252
- (Ctx.LangOpts .DisableAvailabilityChecking
253
- ? AvailabilityContext::alwaysAvailable ()
254
- : TypeChecker::overApproximateAvailabilityAtLocation (loc, DC));
255
-
256
+ auto runningOSVersion = availabilityAtLocation (loc, DC);
256
257
bool spi = Ctx.LangOpts .LibraryLevel == LibraryLevel::SPI;
257
258
bool implicit = false ;
258
259
bool deprecated = false ;
@@ -294,6 +295,14 @@ ExportContext ExportContext::withExported(bool exported) const {
294
295
return copy;
295
296
}
296
297
298
+ ExportContext ExportContext::withRefinedAvailability (const Decl *decl) const {
299
+ auto copy = *this ;
300
+ auto runningOSVersion =
301
+ availabilityAtLocation (decl->getLoc (), decl->getInnermostDeclContext ());
302
+ copy.RunningOSVersion .intersectWith (runningOSVersion);
303
+ return copy;
304
+ }
305
+
297
306
std::optional<PlatformKind> ExportContext::getUnavailablePlatformKind () const {
298
307
if (Unavailable)
299
308
return PlatformKind (Platform);
@@ -4536,6 +4545,94 @@ swift::diagnoseSubstitutionMapAvailability(SourceLoc loc,
4536
4545
return hadAnyIssues;
4537
4546
}
4538
4547
4548
+ static bool diagnoseExplicitUnavailabilityForTypeWitness (
4549
+ const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4550
+ const ExportContext &where) {
4551
+ auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (witness, where);
4552
+ if (!diagnosticInfo)
4553
+ return false ;
4554
+
4555
+ ASTContext &ctx = witness->getASTContext ();
4556
+ auto &diags = ctx.Diags ;
4557
+ auto proto = assocType->getProtocol ();
4558
+ StringRef platform = diagnosticInfo->getPlatform ();
4559
+ const AvailableAttr *attr = diagnosticInfo->getAttr ();
4560
+
4561
+ EncodedDiagnosticMessage EncodedMessage (attr->Message );
4562
+ diags.diagnose (witness, diag::type_witness_availability_unavailable, witness,
4563
+ assocType, proto, platform.empty (), platform,
4564
+ EncodedMessage.Message );
4565
+
4566
+ switch (diagnosticInfo->getStatus ()) {
4567
+ case UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable:
4568
+ diags
4569
+ .diagnose (witness, diag::type_witness_availability_marked_unavailable,
4570
+ witness, assocType, proto)
4571
+ .highlight (attr->getRange ());
4572
+ break ;
4573
+ case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion:
4574
+ diags.diagnose (witness,
4575
+ diag::type_witness_availability_introduced_in_version,
4576
+ witness, assocType, proto,
4577
+ diagnosticInfo->getVersionedPlatform (), *attr->Introduced );
4578
+ break ;
4579
+ case UnavailabilityDiagnosticInfo::Status::Obsoleted:
4580
+ diags
4581
+ .diagnose (witness, diag::type_witness_availability_obsoleted, witness,
4582
+ assocType, proto, diagnosticInfo->getVersionedPlatform (),
4583
+ *attr->Obsoleted )
4584
+ .highlight (attr->getRange ());
4585
+ break ;
4586
+ }
4587
+ return true ;
4588
+ }
4589
+
4590
+ static void diagnosePotentialUnavailabilityForTypeWitness (
4591
+ const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4592
+ const DeclContext *dc, const UnavailabilityReason &reason) {
4593
+ auto &ctx = dc->getASTContext ();
4594
+ auto proto = assocType->getProtocol ();
4595
+ auto requiredRange = reason.getRequiredOSVersionRange ();
4596
+ auto loc = witness->getLoc ();
4597
+
4598
+ {
4599
+ auto err = ctx.Diags .diagnose (
4600
+ loc, diag::type_witness_availability_only_version_newer, witness,
4601
+ assocType, proto, prettyPlatformString (targetPlatform (ctx.LangOpts )),
4602
+ requiredRange.getLowerEndpoint ());
4603
+
4604
+ // Direct a fixit to the error if an existing guard is nearly-correct
4605
+ if (fixAvailabilityByNarrowingNearbyVersionCheck (loc, dc, requiredRange,
4606
+ ctx, err))
4607
+ return ;
4608
+ }
4609
+
4610
+ fixAvailability (loc, dc, requiredRange, ctx);
4611
+ }
4612
+
4613
+ bool swift::diagnoseTypeWitnessAvailability (const TypeDecl *witness,
4614
+ const AssociatedTypeDecl *assocType,
4615
+ const ExportContext &where) {
4616
+ assert (!where.isImplicit ());
4617
+
4618
+ if (witness->isInvalid ())
4619
+ return false ;
4620
+
4621
+ if (diagnoseExplicitUnavailabilityForTypeWitness (witness, assocType, where))
4622
+ return true ;
4623
+
4624
+ auto dc = where.getDeclContext ();
4625
+ auto maybeUnavail = TypeChecker::checkDeclarationAvailability (
4626
+ witness, where.withRefinedAvailability (assocType));
4627
+ if (maybeUnavail.has_value ()) {
4628
+ diagnosePotentialUnavailabilityForTypeWitness (witness, assocType, dc,
4629
+ *maybeUnavail);
4630
+ return true ;
4631
+ }
4632
+
4633
+ return false ;
4634
+ }
4635
+
4539
4636
// / Should we warn that \p decl needs an explicit availability annotation
4540
4637
// / in -require-explicit-availability mode?
4541
4638
static bool declNeedsExplicitAvailability (const Decl *decl) {
0 commit comments