diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 9e2d753802488..fb10cf82419e4 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -4781,13 +4781,18 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation( case ActorIsolation::ActorInstance: { if (checkIsolatedCapture) { + if (auto param = closure->getCaptureInfo().getIsolatedParamCapture()) + return ActorIsolation::forActorInstanceCapture(param); + auto *explicitClosure = dyn_cast(closure); // @_inheritActorContext(always) forces the isolation capture. - if (explicitClosure && explicitClosure->alwaysInheritsActorContext()) + if (explicitClosure && explicitClosure->alwaysInheritsActorContext()) { + if (parentIsolation.isActorInstanceIsolated()) { + if (auto *param = parentIsolation.getActorInstance()) + return ActorIsolation::forActorInstanceCapture(param); + } return parentIsolation; - - if (auto param = closure->getCaptureInfo().getIsolatedParamCapture()) - return ActorIsolation::forActorInstanceCapture(param); + } } else { // If we don't have capture information during code completion, assume // that the closure captures the `isolated` parameter from the parent diff --git a/test/SILGen/hop_to_executor.swift b/test/SILGen/hop_to_executor.swift index 8a0d6334aef13..a1daf20bed2c5 100644 --- a/test/SILGen/hop_to_executor.swift +++ b/test/SILGen/hop_to_executor.swift @@ -325,6 +325,7 @@ func testGlobalActorFuncValue(_ fn: @RedActor () -> Void) async { func acceptAsyncSendableClosureInheriting(@_inheritActorContext _: @Sendable () async -> T) { } func acceptAsyncSendableClosureAlwaysInheriting(@_inheritActorContext(always) _: @Sendable () async -> T) { } +func acceptAsyncSendableClosureAlwaysInheritingErased(@_inheritActorContext(always) _: sending @isolated(any) () async -> T) { } extension MyActor { func synchronous() { } @@ -385,6 +386,22 @@ func testIsolatedParameterWithInheritActorContext(_ isolation: isolated (any Act } } +// CHECK-LABEL: sil hidden [ossa] @$s4test0a17IsolatedParamWithB3AnyyyScA_pYiF +// CHECK: [[CLOSURE_REF:%.*]] = function_ref @$s4test0a17IsolatedParamWithB3AnyyyScA_pYiFyyYaXEfU_ +// CHECK-NEXT: [[ISOLATION_COPY_1:%.*]] = copy_value %0 : $any Actor +// CHECK-NEXT: [[ISOLATION_COPY_2:%.*]] = copy_value [[ISOLATION_COPY_1]] : $any Actor +// CHECK-NEXT: [[DYNAMIC_ISOLATION:%.*]] = enum $Optional, #Optional.some!enumelt, [[ISOLATION_COPY_2]] : $any Actor +// CHECK-NEXT: [[CLOSURE_WITH_APPLIED_ISOLATION:%.*]] = partial_apply [callee_guaranteed] [isolated_any] [[CLOSURE_REF]]([[DYNAMIC_ISOLATION]], [[ISOLATION_COPY_1]]) +func testIsolatedParamWithIsolatedAny(_ isolation: isolated any Actor) { + // CHECK-LABEL: sil private [ossa] @$s4test0a17IsolatedParamWithB3AnyyyScA_pYiFyyYaXEfU_ + // CHECK: bb0(%0 : $*(), [[DYNAMIC_ISOLATION:%[0-9]+]] : @guaranteed $Optional, [[CAPTURED_ISOLATION:%[0-9]+]] : @closureCapture @guaranteed $any Actor): + // CHECK: [[COPY:%[0-9]+]] = copy_value [[CAPTURED_ISOLATION]] : $any Actor + // CHECK-NEXT: [[BORROW:%[0-9]+]] = begin_borrow [[COPY]] : $any Actor + // CHECK-NEXT: hop_to_executor [[BORROW]] : $any Actor + acceptAsyncSendableClosureAlwaysInheritingErased { + } +} + func acceptAsyncClosure(_: () async -> Void) { } func acceptAsyncClosure2(_: (T) async -> T) { }