Skip to content

Commit 5d337f7

Browse files
committed
Diagnose unsafe global variable accesses within concurrent closures/functions.
Concurrent closures and functions are, of course... concurrent. Treat them as such for the warnings about unsafe accesses to global variables.
1 parent a554ad6 commit 5d337f7

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,18 +2025,21 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
20252025
static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
20262026
while (!dc->isModuleScopeContext()) {
20272027
if (auto closure = dyn_cast<AbstractClosureExpr>(dc)) {
2028-
// Async closures use concurrency features.
2029-
if (closure->getType() && closure->isBodyAsync())
2030-
return true;
2028+
// Async and concurrent closures use concurrency features.
2029+
if (auto closureType = closure->getType()) {
2030+
if (auto fnType = closureType->getAs<AnyFunctionType>())
2031+
if (fnType->isAsync() || fnType->isConcurrent())
2032+
return true;
2033+
}
20312034
} else if (auto decl = dc->getAsDecl()) {
20322035
// If any isolation attributes are present, we're using concurrency
20332036
// features.
20342037
if (getIsolationFromAttributes(decl, /*shouldDiagnose=*/false))
20352038
return true;
20362039

20372040
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
2038-
// Async functions use concurrency features.
2039-
if (func->hasAsync())
2041+
// Async and concurrent functions use concurrency features.
2042+
if (func->hasAsync() || func->isConcurrent())
20402043
return true;
20412044

20422045
// If there is an explicit @asyncHandler, we're using concurrency

test/Concurrency/actor_isolation.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// REQUIRES: concurrency
33

44
let immutableGlobal: String = "hello"
5-
var mutableGlobal: String = "can't touch this" // expected-note 3{{var declared here}}
5+
var mutableGlobal: String = "can't touch this" // expected-note 5{{var declared here}}
66

77
func globalFunc() { }
88
func acceptClosure<T>(_: () -> T) { }
@@ -334,6 +334,16 @@ func testGlobalRestrictions(actor: MyActor) async {
334334
print(i)
335335
}
336336

337+
func f() {
338+
acceptConcurrentClosure {
339+
_ = mutableGlobal // expected-warning{{reference to var 'mutableGlobal' is not concurrency-safe because it involves shared mutable state}}
340+
}
341+
342+
@concurrent func g() {
343+
_ = mutableGlobal // expected-warning{{reference to var 'mutableGlobal' is not concurrency-safe because it involves shared mutable state}}
344+
}
345+
}
346+
337347
// ----------------------------------------------------------------------
338348
// Local function isolation restrictions
339349
// ----------------------------------------------------------------------

0 commit comments

Comments
 (0)