Skip to content

Commit c6cafd3

Browse files
authored
Merge pull request #81881 from hborla/6.2-isolated-capture-fixes
[6.2][Concurrency] Fix a false-positive metatype capture diagnostic.
2 parents 837ed71 + 61a2143 commit c6cafd3

File tree

2 files changed

+23
-24
lines changed

2 files changed

+23
-24
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 10 additions & 24 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,13 +4832,12 @@ 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;
48414840

4842-
bool isolatedStateMayEscape = false;
4843-
48444841
auto useIsolation = getActorIsolationOfContext(
48454842
const_cast<DeclContext *>(useContext), getClosureActorIsolation);
48464843
if (useIsolation.isActorIsolated()) {
@@ -4858,16 +4855,6 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48584855
if (ctx.LangOpts.hasFeature(Feature::GlobalActorIsolatedTypesUsability) &&
48594856
regionIsolationEnabled && useIsolation.isGlobalActor())
48604857
return false;
4861-
4862-
// If the local function is not Sendable, its isolation differs
4863-
// from that of the context, and both contexts are actor isolated,
4864-
// then capturing non-Sendable values allows the closure to stash
4865-
// those values into actor isolated state. The original context
4866-
// may also stash those values into isolated state, enabling concurrent
4867-
// access later on.
4868-
isolatedStateMayEscape =
4869-
(!regionIsolationEnabled &&
4870-
useIsolation.isActorIsolated() && defIsolation.isActorIsolated());
48714858
}
48724859

48734860
// Walk the context chain from the use to the definition.
@@ -4877,18 +4864,17 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48774864
if (closure->isSendable())
48784865
return true;
48794866

4880-
if (isolatedStateMayEscape)
4881-
return true;
4867+
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4868+
if (includeSending && explicitClosure->isPassedToSendingParameter())
4869+
return true;
4870+
}
48824871
}
48834872

48844873
if (auto func = dyn_cast<FuncDecl>(useContext)) {
48854874
if (func->isLocalCapture()) {
48864875
// If the function is @Sendable... it can be run concurrently.
48874876
if (func->isSendable())
48884877
return true;
4889-
4890-
if (isolatedStateMayEscape)
4891-
return true;
48924878
}
48934879
}
48944880

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)