Skip to content

Commit d69010e

Browse files
authored
Merge pull request #69332 from hborla/5.10-inout-async-downgrade
[5.10][Concurrency] Downgrade `actor_isolated_mutating_func` to a warning in a narrow case that was previously accepted.
2 parents 1e03616 + fceaaa1 commit d69010e

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2761,7 +2761,8 @@ namespace {
27612761
return false;
27622762

27632763
bool result = false;
2764-
auto diagnoseIsolatedInoutState = [this, call, isPartialApply, &result](
2764+
bool downgradeToWarning = false;
2765+
auto diagnoseIsolatedInoutState = [&](
27652766
ConcreteDeclRef declRef, SourceLoc argLoc) {
27662767
auto decl = declRef.getDecl();
27672768
auto isolation = getActorIsolationForReference(decl, getDeclContext());
@@ -2778,7 +2779,8 @@ namespace {
27782779
ValueDecl *fnDecl = declRef->getDecl();
27792780
ctx.Diags.diagnose(apply->getLoc(),
27802781
diag::actor_isolated_mutating_func,
2781-
fnDecl->getName(), decl);
2782+
fnDecl->getName(), decl)
2783+
.warnUntilSwiftVersionIf(downgradeToWarning, 6);
27822784
result = true;
27832785
return;
27842786
}
@@ -2801,6 +2803,11 @@ namespace {
28012803
};
28022804

28032805
auto findIsolatedState = [&](Expr *expr) -> Expr * {
2806+
// This code used to not walk into InOutExpr, which allowed
2807+
// some invalid code to slip by in compilers <=5.9.
2808+
if (isa<InOutExpr>(expr))
2809+
downgradeToWarning = true;
2810+
28042811
if (LookupExpr *lookup = dyn_cast<LookupExpr>(expr)) {
28052812
if (isa<DeclRefExpr>(lookup->getBase())) {
28062813
diagnoseIsolatedInoutState(lookup->getMember().getDecl(),

test/Concurrency/actor_inout_isolation.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,18 @@ actor ProtectArray {
307307
}
308308
}
309309
}
310+
311+
extension Optional {
312+
mutating func mutate() async {}
313+
}
314+
315+
@available(SwiftStdlib 5.1, *)
316+
actor ProtectDictionary {
317+
var dict: [Int: Int] = [:]
318+
319+
func invalid() async {
320+
await dict[0].mutate()
321+
// expected-warning@-1 {{cannot call mutating async function 'mutate()' on actor-isolated property 'dict'; this is an error in Swift 6}}
322+
// expected-targeted-complete-warning@-2 {{passing argument of non-sendable type 'inout Optional<Int>' outside of actor-isolated context may introduce data races}}
323+
}
324+
}

0 commit comments

Comments
 (0)