@@ -3593,17 +3593,9 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
3593
3593
3594
3594
ExprStack.push_back (E);
3595
3595
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));
3607
3599
}
3608
3600
3609
3601
if (auto DR = dyn_cast<DeclRefExpr>(E)) {
@@ -3629,6 +3621,8 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
3629
3621
if (S->hasDecl ()) {
3630
3622
diagnoseDeclRefAvailability (S->getDecl (), S->getSourceRange (), S);
3631
3623
maybeDiagStorageAccess (S->getDecl ().getDecl (), S->getSourceRange (), DC);
3624
+ PreconcurrencyCalleeStack.push_back (
3625
+ hasReferenceToPreconcurrencyDecl (S));
3632
3626
}
3633
3627
}
3634
3628
@@ -4007,6 +4001,41 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
4007
4001
Flags))
4008
4002
return ;
4009
4003
}
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
+ }
4010
4039
};
4011
4040
} // end anonymous namespace
4012
4041
0 commit comments