@@ -216,15 +216,20 @@ computeExportContextBits(ASTContext &Ctx, Decl *D, bool *spi, bool *implicit,
216
216
}
217
217
}
218
218
219
+ static AvailabilityContext availabilityAtLocation (SourceLoc loc,
220
+ const DeclContext *dc) {
221
+ auto &ctx = dc->getASTContext ();
222
+ return ctx.LangOpts .DisableAvailabilityChecking
223
+ ? AvailabilityContext::alwaysAvailable ()
224
+ : TypeChecker::overApproximateAvailabilityAtLocation (loc, dc);
225
+ }
226
+
219
227
ExportContext ExportContext::forDeclSignature (Decl *D) {
220
228
auto &Ctx = D->getASTContext ();
221
229
222
230
auto *DC = D->getInnermostDeclContext ();
223
231
auto fragileKind = DC->getFragileFunctionKind ();
224
- auto runningOSVersion =
225
- (Ctx.LangOpts .DisableAvailabilityChecking
226
- ? AvailabilityContext::alwaysAvailable ()
227
- : TypeChecker::overApproximateAvailabilityAtLocation (D->getLoc (), DC));
232
+ auto runningOSVersion = availabilityAtLocation (D->getLoc (), DC);
228
233
bool spi = Ctx.LangOpts .LibraryLevel == LibraryLevel::SPI;
229
234
bool implicit = false ;
230
235
bool deprecated = false ;
@@ -249,11 +254,7 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
249
254
auto &Ctx = DC->getASTContext ();
250
255
251
256
auto fragileKind = DC->getFragileFunctionKind ();
252
- auto runningOSVersion =
253
- (Ctx.LangOpts .DisableAvailabilityChecking
254
- ? AvailabilityContext::alwaysAvailable ()
255
- : TypeChecker::overApproximateAvailabilityAtLocation (loc, DC));
256
-
257
+ auto runningOSVersion = availabilityAtLocation (loc, DC);
257
258
bool spi = Ctx.LangOpts .LibraryLevel == LibraryLevel::SPI;
258
259
bool implicit = false ;
259
260
bool deprecated = false ;
@@ -295,6 +296,13 @@ ExportContext ExportContext::withExported(bool exported) const {
295
296
return copy;
296
297
}
297
298
299
+ ExportContext
300
+ ExportContext::withRefinedAvailability (AvailabilityContext availability) const {
301
+ auto copy = *this ;
302
+ copy.RunningOSVersion .intersectWith (availability);
303
+ return copy;
304
+ }
305
+
298
306
std::optional<PlatformKind> ExportContext::getUnavailablePlatformKind () const {
299
307
if (Unavailable)
300
308
return PlatformKind (Platform);
@@ -4582,6 +4590,104 @@ swift::diagnoseSubstitutionMapAvailability(SourceLoc loc,
4582
4590
return hadAnyIssues;
4583
4591
}
4584
4592
4593
+ static bool diagnoseExplicitUnavailabilityForTypeWitness (
4594
+ const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4595
+ const ExportContext &where) {
4596
+ auto diagnosticInfo = getExplicitUnavailabilityDiagnosticInfo (witness, where);
4597
+ if (!diagnosticInfo)
4598
+ return false ;
4599
+
4600
+ ASTContext &ctx = witness->getASTContext ();
4601
+ auto &diags = ctx.Diags ;
4602
+ auto proto = assocType->getProtocol ();
4603
+ StringRef platform = diagnosticInfo->getPlatform ();
4604
+ const AvailableAttr *attr = diagnosticInfo->getAttr ();
4605
+
4606
+ EncodedDiagnosticMessage EncodedMessage (attr->Message );
4607
+ diags.diagnose (witness, diag::type_witness_availability_unavailable, witness,
4608
+ assocType, proto, platform.empty (), platform,
4609
+ EncodedMessage.Message );
4610
+
4611
+ switch (diagnosticInfo->getStatus ()) {
4612
+ case UnavailabilityDiagnosticInfo::Status::AlwaysUnavailable:
4613
+ diags
4614
+ .diagnose (witness, diag::type_witness_availability_marked_unavailable,
4615
+ witness, assocType, proto)
4616
+ .highlight (attr->getRange ());
4617
+ break ;
4618
+ case UnavailabilityDiagnosticInfo::Status::IntroducedInVersion:
4619
+ diags.diagnose (witness,
4620
+ diag::type_witness_availability_introduced_in_version,
4621
+ witness, assocType, proto,
4622
+ diagnosticInfo->getVersionedPlatform (), *attr->Introduced );
4623
+ break ;
4624
+ case UnavailabilityDiagnosticInfo::Status::Obsoleted:
4625
+ diags
4626
+ .diagnose (witness, diag::type_witness_availability_obsoleted, witness,
4627
+ assocType, proto, diagnosticInfo->getVersionedPlatform (),
4628
+ *attr->Obsoleted )
4629
+ .highlight (attr->getRange ());
4630
+ break ;
4631
+ }
4632
+ return true ;
4633
+ }
4634
+
4635
+ static void diagnosePotentialUnavailabilityForTypeWitness (
4636
+ const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4637
+ const DeclContext *dc, const UnavailabilityReason &reason) {
4638
+ auto &ctx = dc->getASTContext ();
4639
+ auto proto = assocType->getProtocol ();
4640
+ auto requiredRange = reason.getRequiredOSVersionRange ();
4641
+ auto loc = witness->getLoc ();
4642
+
4643
+ {
4644
+ auto err = ctx.Diags .diagnose (
4645
+ loc, diag::type_witness_availability_only_version_newer, witness,
4646
+ assocType, proto, prettyPlatformString (targetPlatform (ctx.LangOpts )),
4647
+ requiredRange.getLowerEndpoint ());
4648
+ err.warnUntilSwiftVersion (7 );
4649
+
4650
+ // Direct a fixit to the error if an existing guard is nearly-correct
4651
+ if (fixAvailabilityByNarrowingNearbyVersionCheck (loc, dc, requiredRange,
4652
+ ctx, err))
4653
+ return ;
4654
+ }
4655
+
4656
+ fixAvailability (loc, dc, requiredRange, ctx);
4657
+ }
4658
+
4659
+ bool swift::diagnoseTypeWitnessAvailability (
4660
+ const TypeDecl *witness, const AssociatedTypeDecl *assocType,
4661
+ const NormalProtocolConformance *conformance, const ExportContext &where) {
4662
+ if (where.isImplicit () || witness->isImplicit ())
4663
+ return false ;
4664
+
4665
+ if (witness->isInvalid ())
4666
+ return false ;
4667
+
4668
+ if (diagnoseExplicitUnavailabilityForTypeWitness (witness, assocType, where))
4669
+ return true ;
4670
+
4671
+ auto dc = conformance->getDeclContext ();
4672
+ auto &ctx = dc->getASTContext ();
4673
+
4674
+ // The witness must be as available as the associated type and the conformance
4675
+ // itself.
4676
+ auto availability = AvailabilityInference::availableRange (assocType, ctx);
4677
+ availability.intersectWith (
4678
+ AvailabilityInference::availableRange (dc->getAsDecl (), ctx));
4679
+
4680
+ auto maybeUnavail = TypeChecker::checkDeclarationAvailability (
4681
+ witness, where.withRefinedAvailability (availability));
4682
+ if (maybeUnavail.has_value ()) {
4683
+ diagnosePotentialUnavailabilityForTypeWitness (witness, assocType, dc,
4684
+ *maybeUnavail);
4685
+ return true ;
4686
+ }
4687
+
4688
+ return false ;
4689
+ }
4690
+
4585
4691
// / Should we warn that \p decl needs an explicit availability annotation
4586
4692
// / in -require-explicit-availability mode?
4587
4693
static bool declNeedsExplicitAvailability (const Decl *decl) {
0 commit comments