@@ -3593,17 +3593,9 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
35933593
35943594 ExprStack.push_back (E);
35953595
3596- if (auto *apply = dyn_cast<ApplyExpr>(E)) {
3597- bool preconcurrency = false ;
3598- auto *fn = apply->getFn ();
3599- if (auto *selfApply = dyn_cast<SelfApplyExpr>(fn)) {
3600- fn = selfApply->getFn ();
3601- }
3602- auto declRef = fn->getReferencedDecl ();
3603- if (auto *decl = declRef.getDecl ()) {
3604- preconcurrency = decl->preconcurrency ();
3605- }
3606- PreconcurrencyCalleeStack.push_back (preconcurrency);
3596+ if (isa<ApplyExpr>(E)) {
3597+ PreconcurrencyCalleeStack.push_back (
3598+ hasReferenceToPreconcurrencyDecl (E));
36073599 }
36083600
36093601 if (auto DR = dyn_cast<DeclRefExpr>(E)) {
@@ -3629,6 +3621,8 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
36293621 if (S->hasDecl ()) {
36303622 diagnoseDeclRefAvailability (S->getDecl (), S->getSourceRange (), S);
36313623 maybeDiagStorageAccess (S->getDecl ().getDecl (), S->getSourceRange (), DC);
3624+ PreconcurrencyCalleeStack.push_back (
3625+ hasReferenceToPreconcurrencyDecl (S));
36323626 }
36333627 }
36343628
@@ -4007,6 +4001,41 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
40074001 Flags))
40084002 return ;
40094003 }
4004+
4005+ // / Check whether the given expression references any
4006+ // / @preconcurrency declarations.
4007+ // / Calls, subscripts, member references can have @preconcurrency
4008+ // / declarations at any point in their base chain.
4009+ bool hasReferenceToPreconcurrencyDecl (Expr *expr) {
4010+ if (auto declRef = expr->getReferencedDecl ()) {
4011+ if (declRef.getDecl ()->preconcurrency ())
4012+ return true ;
4013+ }
4014+
4015+ if (auto *selfApply = dyn_cast<SelfApplyExpr>(expr)) {
4016+ if (hasReferenceToPreconcurrencyDecl (selfApply->getFn ()))
4017+ return true ;
4018+
4019+ // Base could be a preconcurrency declaration i.e.
4020+ //
4021+ // @preconcurrency var x: [any Sendable]
4022+ // x.append(...)
4023+ //
4024+ // If thought `append` might not be `@preconcurrency`
4025+ // the "base" is.
4026+ return hasReferenceToPreconcurrencyDecl (selfApply->getBase ());
4027+ }
4028+
4029+ if (auto *LE = dyn_cast<LookupExpr>(expr)) {
4030+ // If subscript itself is not @preconcurrency, it's base could be.
4031+ return hasReferenceToPreconcurrencyDecl (LE->getBase ());
4032+ }
4033+
4034+ if (auto *apply = dyn_cast<ApplyExpr>(expr))
4035+ return hasReferenceToPreconcurrencyDecl (apply->getFn ());
4036+
4037+ return false ;
4038+ }
40104039};
40114040} // end anonymous namespace
40124041
0 commit comments