@@ -397,6 +397,27 @@ static bool shouldAllowReferenceToUnavailableInSwiftDeclaration(
397
397
return false ;
398
398
}
399
399
400
+ // Utility function to help determine if noasync diagnostics are still
401
+ // appropriate even if a `DeclContext` returns `false` from `isAsyncContext()`.
402
+ static bool
403
+ shouldTreatDeclContextAsAsyncForDiagnostics (const DeclContext *DC) {
404
+ switch (DC->getContextKind ()) {
405
+ case DeclContextKind::AbstractFunctionDecl: {
406
+ auto *FD = dyn_cast<FuncDecl>(DC->getAsDecl ());
407
+ if (FD && FD->isDeferBody ()) {
408
+ // If this is a defer body, we should delegate the determination
409
+ // to its parent.
410
+ return shouldTreatDeclContextAsAsyncForDiagnostics (DC->getParent ());
411
+ } else {
412
+ return DC->isAsyncContext ();
413
+ }
414
+ }
415
+
416
+ default :
417
+ return DC->isAsyncContext ();
418
+ }
419
+ }
420
+
400
421
namespace {
401
422
402
423
// / A class to walk the AST to build the type refinement context hierarchy.
@@ -3781,17 +3802,20 @@ bool ExprAvailabilityWalker::diagnoseDeclRefAvailability(
3781
3802
static bool
3782
3803
diagnoseDeclAsyncAvailability (const ValueDecl *D, SourceRange R,
3783
3804
const Expr *call, const ExportContext &Where) {
3784
- // If we are in a synchronous context, don't check it
3785
- if (!Where.getDeclContext ()-> isAsyncContext ( ))
3805
+ // If we are not in an (effective) async context, don't check it
3806
+ if (!shouldTreatDeclContextAsAsyncForDiagnostics ( Where.getDeclContext ()))
3786
3807
return false ;
3787
3808
3788
3809
ASTContext &ctx = Where.getDeclContext ()->getASTContext ();
3789
3810
3790
- if (const AbstractFunctionDecl *afd = dyn_cast<AbstractFunctionDecl>(D)) {
3791
- if (const AbstractFunctionDecl *asyncAlt = afd->getAsyncAlternative ()) {
3792
- SourceLoc diagLoc = call ? call->getLoc () : R.Start ;
3793
- ctx.Diags .diagnose (diagLoc, diag::warn_use_async_alternative);
3794
- asyncAlt->diagnose (diag::decl_declared_here, asyncAlt);
3811
+ // Only suggest async alternatives if the DeclContext is truly async
3812
+ if (Where.getDeclContext ()->isAsyncContext ()) {
3813
+ if (const AbstractFunctionDecl *afd = dyn_cast<AbstractFunctionDecl>(D)) {
3814
+ if (const AbstractFunctionDecl *asyncAlt = afd->getAsyncAlternative ()) {
3815
+ SourceLoc diagLoc = call ? call->getLoc () : R.Start ;
3816
+ ctx.Diags .diagnose (diagLoc, diag::warn_use_async_alternative);
3817
+ asyncAlt->diagnose (diag::decl_declared_here, asyncAlt);
3818
+ }
3795
3819
}
3796
3820
}
3797
3821
0 commit comments