Skip to content

Commit 61a2143

Browse files
committed
[Concurrency] Don't diagnose metatype captures in closures that are
isolated to the same actor as the enclosing context. (cherry picked from commit f0e77c7)
1 parent bbc3c42 commit 61a2143

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,7 +2559,8 @@ namespace {
25592559
/// Determine whether code in the given use context might execute
25602560
/// concurrently with code in the definition context.
25612561
bool mayExecuteConcurrentlyWith(
2562-
const DeclContext *useContext, const DeclContext *defContext);
2562+
const DeclContext *useContext, const DeclContext *defContext,
2563+
bool includeSending = false);
25632564

25642565
/// If the subexpression is a reference to a mutable local variable from a
25652566
/// different context, record its parent. We'll query this as part of
@@ -3067,12 +3068,9 @@ namespace {
30673068
}
30683069
}
30693070

3070-
// FIXME: When passing to a sending parameter, should this be handled
3071-
// by region isolation? Or should it always be handled by region
3072-
// isolation?
30733071
if (mayExecuteConcurrentlyWith(
3074-
localFunc.getAsDeclContext(), getDeclContext()) ||
3075-
(explicitClosure && explicitClosure->isPassedToSendingParameter())) {
3072+
localFunc.getAsDeclContext(), getDeclContext(),
3073+
/*includeSending*/true)) {
30763074
auto innermostGenericDC = localFunc.getAsDeclContext();
30773075
while (innermostGenericDC && !innermostGenericDC->isGenericContext())
30783076
innermostGenericDC = innermostGenericDC->getParent();
@@ -4834,7 +4832,8 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
48344832
}
48354833

48364834
bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
4837-
const DeclContext *useContext, const DeclContext *defContext) {
4835+
const DeclContext *useContext, const DeclContext *defContext,
4836+
bool includeSending) {
48384837
// Fast path for when the use and definition contexts are the same.
48394838
if (useContext == defContext)
48404839
return false;
@@ -4865,6 +4864,10 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48654864
if (closure->isSendable())
48664865
return true;
48674866

4867+
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4868+
if (includeSending && explicitClosure->isPassedToSendingParameter())
4869+
return true;
4870+
}
48684871
}
48694872

48704873
if (auto func = dyn_cast<FuncDecl>(useContext)) {

test/Concurrency/sendable_metatype_typecheck.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,16 @@ extension TestUnapplied {
175175
func testUnappliedWithOpetator<T: Comparable>(v: TestUnapplied<T>) {
176176
v<=>(>) // expected-error {{converting non-Sendable function value to '@Sendable (T, T) -> Bool' may introduce data races}}
177177
}
178+
179+
protocol P {}
180+
181+
func acceptClosure(_: () -> Void) {}
182+
183+
@MainActor
184+
func f<T: P>(_: T.Type) {
185+
acceptClosure {
186+
Task {
187+
_ = T.self // okay to capture T.Type in this closure.
188+
}
189+
}
190+
}

0 commit comments

Comments
 (0)