Skip to content

Commit 5f3f845

Browse files
authored
Merge pull request #69330 from hborla/inout-async-downgrade
[Concurrency] Downgrade `actor_isolated_mutating_func` to a warning in a narrow case that was previously accepted.
2 parents b343404 + 936739e commit 5f3f845

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
@@ -2760,7 +2760,8 @@ namespace {
27602760
return false;
27612761

27622762
bool result = false;
2763-
auto diagnoseIsolatedInoutState = [this, call, isPartialApply, &result](
2763+
bool downgradeToWarning = false;
2764+
auto diagnoseIsolatedInoutState = [&](
27642765
ConcreteDeclRef declRef, SourceLoc argLoc) {
27652766
auto decl = declRef.getDecl();
27662767
auto isolation = getActorIsolationForReference(decl, getDeclContext());
@@ -2777,7 +2778,8 @@ namespace {
27772778
ValueDecl *fnDecl = declRef->getDecl();
27782779
ctx.Diags.diagnose(apply->getLoc(),
27792780
diag::actor_isolated_mutating_func,
2780-
fnDecl->getName(), decl);
2781+
fnDecl->getName(), decl)
2782+
.warnUntilSwiftVersionIf(downgradeToWarning, 6);
27812783
result = true;
27822784
return;
27832785
}
@@ -2800,6 +2802,11 @@ namespace {
28002802
};
28012803

28022804
auto findIsolatedState = [&](Expr *expr) -> Expr * {
2805+
// This code used to not walk into InOutExpr, which allowed
2806+
// some invalid code to slip by in compilers <=5.9.
2807+
if (isa<InOutExpr>(expr))
2808+
downgradeToWarning = true;
2809+
28032810
if (LookupExpr *lookup = dyn_cast<LookupExpr>(expr)) {
28042811
if (isa<DeclRefExpr>(lookup->getBase())) {
28052812
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)