@@ -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
@@ -3677,6 +3671,11 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
3677
3671
maybeDiagKeyPath (KP);
3678
3672
}
3679
3673
if (auto A = dyn_cast<AssignExpr>(E)) {
3674
+ // Attempting to assign to a @preconcurrency declaration should
3675
+ // downgrade Sendable conformance mismatches to warnings.
3676
+ PreconcurrencyCalleeStack.push_back (
3677
+ hasReferenceToPreconcurrencyDecl (A->getDest ()));
3678
+
3680
3679
walkAssignExpr (A);
3681
3680
return Action::SkipChildren (E);
3682
3681
}
@@ -4007,6 +4006,41 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
4007
4006
Flags))
4008
4007
return ;
4009
4008
}
4009
+
4010
+ // / Check whether the given expression references any
4011
+ // / @preconcurrency declarations.
4012
+ // / Calls, subscripts, member references can have @preconcurrency
4013
+ // / declarations at any point in their base chain.
4014
+ bool hasReferenceToPreconcurrencyDecl (Expr *expr) {
4015
+ if (auto declRef = expr->getReferencedDecl ()) {
4016
+ if (declRef.getDecl ()->preconcurrency ())
4017
+ return true ;
4018
+ }
4019
+
4020
+ if (auto *selfApply = dyn_cast<SelfApplyExpr>(expr)) {
4021
+ if (hasReferenceToPreconcurrencyDecl (selfApply->getFn ()))
4022
+ return true ;
4023
+
4024
+ // Base could be a preconcurrency declaration i.e.
4025
+ //
4026
+ // @preconcurrency var x: [any Sendable]
4027
+ // x.append(...)
4028
+ //
4029
+ // If thought `append` might not be `@preconcurrency`
4030
+ // the "base" is.
4031
+ return hasReferenceToPreconcurrencyDecl (selfApply->getBase ());
4032
+ }
4033
+
4034
+ if (auto *LE = dyn_cast<LookupExpr>(expr)) {
4035
+ // If subscript itself is not @preconcurrency, it's base could be.
4036
+ return hasReferenceToPreconcurrencyDecl (LE->getBase ());
4037
+ }
4038
+
4039
+ if (auto *apply = dyn_cast<ApplyExpr>(expr))
4040
+ return hasReferenceToPreconcurrencyDecl (apply->getFn ());
4041
+
4042
+ return false ;
4043
+ }
4010
4044
};
4011
4045
} // end anonymous namespace
4012
4046
0 commit comments