Skip to content

Commit a492ccc

Browse files
committed
[Concurrency] Don't diagnose metatype captures in closures that are
isolated to the same actor as the enclosing context.
1 parent c283ce1 commit a492ccc

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,8 @@ namespace {
25432543
/// Determine whether code in the given use context might execute
25442544
/// concurrently with code in the definition context.
25452545
bool mayExecuteConcurrentlyWith(
2546-
const DeclContext *useContext, const DeclContext *defContext);
2546+
const DeclContext *useContext, const DeclContext *defContext,
2547+
bool includeSending = false);
25472548

25482549
/// If the subexpression is a reference to a mutable local variable from a
25492550
/// different context, record its parent. We'll query this as part of
@@ -3055,8 +3056,8 @@ namespace {
30553056
// by region isolation? Or should it always be handled by region
30563057
// isolation?
30573058
if (mayExecuteConcurrentlyWith(
3058-
localFunc.getAsDeclContext(), getDeclContext()) ||
3059-
(explicitClosure && explicitClosure->isPassedToSendingParameter())) {
3059+
localFunc.getAsDeclContext(), getDeclContext(),
3060+
/*includeSending*/true)) {
30603061
auto innermostGenericDC = localFunc.getAsDeclContext();
30613062
while (innermostGenericDC && !innermostGenericDC->isGenericContext())
30623063
innermostGenericDC = innermostGenericDC->getParent();
@@ -4816,7 +4817,8 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
48164817
}
48174818

48184819
bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
4819-
const DeclContext *useContext, const DeclContext *defContext) {
4820+
const DeclContext *useContext, const DeclContext *defContext,
4821+
bool includeSending) {
48204822
// Fast path for when the use and definition contexts are the same.
48214823
if (useContext == defContext)
48224824
return false;
@@ -4847,6 +4849,10 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48474849
if (closure->isSendable())
48484850
return true;
48494851

4852+
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4853+
if (includeSending && explicitClosure->isPassedToSendingParameter())
4854+
return true;
4855+
}
48504856
}
48514857

48524858
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)