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