[concurrency] Ensure that we treat closures that are nonisolated(nonsending) via their ActorIsolation as nonisolated(nonsending).

Some notes:

1. In most cases, I think we were getting lucky with this by just inferring the
closure's isolation from its decl context. In the specific case that we were
looking at here, this was not true since we are returning from an @concurrent
async function a nonisolated(nonsending) method that closes over self. This
occurs since even when NonisolatedNonsendingByDefault we want to start importing
objc async functions as nonisolated(nonsending).

2. I also discovered that in the ActorIsolationChecker we were not visiting the
inner autoclosure meaning that we never set the ActorIsolation field on the
closure. After some discussion with @xedin about potentially visiting the
function in the ActorIsolationChecker, we came to the conclusion that this was
likely to result in source stability changes. So we put in a targeted fix just
for autoclosures in this specific case by setting their actor isolation in the
type checker.

3. Beyond adding tests to objc_async_from_swift to make sure that when
NonisolatedNonsendingByDefault is disabled we do the right thing, I noticed that
we did not have any tests that actually tested the behavior around
objc_async_from_swift when NonisolatedNonsendingByDefault is enabled. So I added
the relevant test lines so we can be sure that we get correct behavior in such a
case.

rdar://150209093
This commit is contained in:
Michael Gottesman
2025-05-06 08:27:46 -07:00
parent 294e4cf21b
commit ced96aa5cd
5 changed files with 419 additions and 78 deletions

View File

@@ -2633,6 +2633,9 @@ static CanSILFunctionType getSILFunctionType(
} else if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
actorIsolation = ActorIsolation::forNonisolated(false /*unsafe*/);
}
} else if (auto *closure = constant->getAbstractClosureExpr()) {
if (auto isolation = closure->getActorIsolation())
actorIsolation = isolation;
}
if (!actorIsolation) {

View File

@@ -765,6 +765,13 @@ static ActorIsolation getActorIsolationForFunction(SILFunction &fn) {
return ActorIsolation::forNonisolated(false);
}
// If we have a closure expr, check if our type is
// nonisolated(nonsending). In that case, we use that instead.
if (auto *closureExpr = constant.getAbstractClosureExpr()) {
if (auto actorIsolation = closureExpr->getActorIsolation())
return actorIsolation;
}
// If we have actor isolation for our constant, put the isolation onto the
// function. If the isolation is unspecified, we do not return it.
if (auto isolation =

View File

@@ -1346,8 +1346,32 @@ namespace {
new (ctx) AutoClosureExpr(/*set body later*/ nullptr, thunkTy, dc);
thunk->setParameterList(thunkParamList);
thunk->setThunkKind(AutoClosureExpr::Kind::SingleCurryThunk);
// TODO: We should do this in the ActorIsolation checker but for now it is
// too risky. This is a narrow fix for 6.2.
//
// The problem that this is working around is given an autoclosure that
// returns an autoclosure that partially applies over an instance method,
// we do not visit the inner autoclosure in the ActorIsolation checker
// meaning that we do not properly call setActorIsolation on the
// AbstractClosureExpr that we produce here.
switch (thunkTy->getIsolation().getKind()) {
case FunctionTypeIsolation::Kind::NonIsolated:
case FunctionTypeIsolation::Kind::Parameter:
case FunctionTypeIsolation::Kind::Erased:
break;
case FunctionTypeIsolation::Kind::GlobalActor:
thunk->setActorIsolation(ActorIsolation::forGlobalActor(
thunkTy->getIsolation().getGlobalActorType()));
break;
case FunctionTypeIsolation::Kind::NonIsolatedCaller:
thunk->setActorIsolation(
ActorIsolation::forCallerIsolationInheriting());
break;
}
cs.cacheType(thunk);
// If the `self` type is existential, it must be opened.
OpaqueValueExpr *baseOpened = nullptr;
Expr *origBaseExpr = baseExpr;

View File

@@ -123,6 +123,16 @@ typedef void (^NonsendableCompletionHandler)(NSString * _Nullable, NSString * _N
__attribute__((swift_async_error(zero_argument, 3)));
- (void)getIceCreamFlavorWithCompletionHandler:
(void (^)(Flavor flavor, NSError *__nullable error))completionHandler;
@property(class, strong, readonly) SlowServer *standardServer;
- (void)getValueWithKey:(NSString *)valueIdentifier
completion:(void (^)(NSString *__nullable value,
NSError *__nullable error))completionHandler;
- (void)getMainActorValueWithKey:(NSString *)valueIdentifier
completion:
(void (^)(NSString *__nullable value,
NSError *__nullable error))completionHandler
MAIN_ACTOR;
@end
@protocol RefrigeratorDelegate<NSObject>

View File

@@ -1,6 +1,10 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -Xllvm -sil-print-types -emit-silgen -I %S/Inputs/custom-modules -target %target-swift-5.1-abi-triple %s -verify | %FileCheck --implicit-check-not=hop_to_executor --check-prefix=CHECK --check-prefix=CHECK-%target-cpu %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -Xllvm -sil-print-types -emit-silgen -I %S/Inputs/custom-modules -target %target-swift-5.1-abi-triple %s -verify | %FileCheck --implicit-check-not=hop_to_executor --check-prefix=CHECK --check-prefix=CHECK-%target-cpu --check-prefix CHECK-C %s
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-upcoming-feature NonisolatedNonsendingByDefault -Xllvm -sil-print-types -emit-silgen -I %S/Inputs/custom-modules -target %target-swift-5.1-abi-triple %s -verify | %FileCheck --implicit-check-not=hop_to_executor --check-prefix=CHECK --check-prefix=CHECK-%target-cpu --check-prefix CHECK-NN %s
// REQUIRES: concurrency
// REQUIRES: objc_interop
// REQUIRES: swift_feature_NonisolatedNonsendingByDefault
import Foundation
import ObjCConcurrency
@@ -15,42 +19,46 @@ import ObjCConcurrency
// CHECK-LABEL: sil {{.*}}@{{.*}}15testSlowServing
func testSlowServing(p: SlowServing) async throws {
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int) -> (), τ_0_0) -> ()
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
let _: Int = await p.requestInt()
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (NSString) -> (), τ_0_0) -> ()
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
let _: String = await p.requestString()
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int, NSString) -> (), τ_0_0) -> ()
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
let _: (Int, String) = await p.requestIntAndString()
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Int, Optional<NSString>, Optional<NSError>) -> (), τ_0_0) -> ()
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK-NEXT: builtin "willThrow"
let _: (Int, String) = try await p.tryRequestIntAndString()
}
// CHECK-LABEL: sil {{.*}}@{{.*}}20testSlowServingAgain
func testSlowServingAgain(p: SlowServing) async throws {
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK: objc_method {{.*}} $@convention(objc_method) <τ_0_0 where τ_0_0 : SlowServing> (@convention(block) (Optional<NSString>, Optional<NSError>) -> (), τ_0_0) -> ()
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK-NEXT: builtin "willThrow"
let _: String = try await p.tryRequestString()
}
class SlowSwiftServer: NSObject, SlowServing {
// CHECK-LABEL: sil {{.*}} @$s21objc_async_from_swift15SlowSwiftServerC10requestIntSiyYaF
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK: } // end sil function '$s21objc_async_from_swift15SlowSwiftServerC10requestIntSiyYaF{{.*}}'
// CHECK-LABEL: sil private {{.*}} @${{.*}}10requestInt{{.*}}To :
// CHECK: [[BLOCK_COPY:%.*]] = copy_block %0
// CHECK: [[SELF:%.*]] = copy_value %1
@@ -66,11 +74,13 @@ class SlowSwiftServer: NSObject, SlowServing {
func requestInt() async -> Int { return 0 }
func requestString() async -> String { return "" }
// CHECK-LABEL: sil {{.*}} @$s21objc_async_from_swift15SlowSwiftServerC13requestStringSSyYaF
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK-LABEL: sil {{.*}} @$s21objc_async_from_swift15SlowSwiftServerC16tryRequestStringSSyYaKF
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
// CHECK-LABEL: sil shared {{.*}} @${{.*}}16tryRequestString{{.*}}U_To :
// CHECK: [[BLOCK_COPY:%.*]] = copy_block %0
// CHECK: try_apply{{.*}}@async{{.*}}, normal [[NORMAL:bb[0-9]+]], error [[ERROR:bb[0-9]+]]
@@ -85,13 +95,15 @@ class SlowSwiftServer: NSObject, SlowServing {
func tryRequestString() async throws -> String { return "" }
// CHECK-LABEL: sil {{.*}} @$s21objc_async_from_swift15SlowSwiftServerC19requestIntAndStringSi_SStyYaF
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
func requestIntAndString() async -> (Int, String) { return (0, "") }
// CHECK-LABEL: sil {{.*}} @$s21objc_async_from_swift15SlowSwiftServerC22tryRequestIntAndStringSi_SStyYaKF
// CHECK: [[GENERIC_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[GENERIC_EXECUTOR]] :
// CHECK-NN: bb0([[HOP_TARGET:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[HOP_TARGET:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
// CHECK: hop_to_executor [[HOP_TARGET]] :
func tryRequestIntAndString() async throws -> (Int, String) { return (0, "") }
}
@@ -108,19 +120,30 @@ extension SlowServer: NativelySlowServing {}
class SlowServerlet: SlowServer {
// Native Function
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> Int
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK: hop_to_executor [[ACTOR]]
// CHECK: // end sil function '$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> Int
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C: hop_to_executor [[ACTOR]]
// CHECK-C: // end sil function '$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF'
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> Int {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF'
// TODO: We are labeling this as having caller_isolation_inheriting when NN
// is enabled... but we do not have an actor parameter. This is incorrect.
//
// @objc thunk closure
//
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaFyyYacfU_To : $@convention(thin) @Sendable @async (NSString, Optional<@convention(block) @Sendable (Int) -> ()>, SlowServerlet) -> () {
// CHECK-NN: [[NONE:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[STR_ARG:%.*]] = begin_borrow {{.*}} : $String
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> Int
// CHECK: apply [[FUNC]]([[STR_ARG]], [[SELF]])
// CHECK-C: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> Int
// CHECK-C: apply [[FUNC]]([[STR_ARG]], [[SELF]])
// CHECK-NN: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> Int
// CHECK-NN: apply [[FUNC]]([[NONE]], [[STR_ARG]], [[SELF]])
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC011doSomethingE8NullablyySiSSYaFyyYacfU_To'
override func doSomethingSlowNullably(_: String) async -> Int {
return 0
@@ -128,18 +151,26 @@ class SlowServerlet: SlowServer {
// Native function.
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> @owned String
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> @owned String
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF'
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> @owned String {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF'
// @objc closure thunk
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaFyyYacfU_To : $@convention(thin) @Sendable @async (NSString, Optional<@convention(block) @Sendable (NSString) -> ()>, SlowServerlet) -> () {
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[STR_ARG:%.*]] = begin_borrow {{.*}} : $String
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> @owned String
// CHECK: apply [[FUNC]]([[STR_ARG]], [[SELF]])
// CHECK-C: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> @owned String
// CHECK-C: apply [[FUNC]]([[STR_ARG]], [[SELF]])
// CHECK-NN: [[FUNC:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> @owned String
// CHECK-NN: apply [[FUNC]]([[ACTOR]], [[STR_ARG]], [[SELF]])
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC18findAnswerNullablyyS2SYaFyyYacfU_To'
override func findAnswerNullably(_ x: String) async -> String {
return x
@@ -147,19 +178,27 @@ class SlowServerlet: SlowServer {
// Native
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF'
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error) {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF'
// @objc thunk closure
//
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKFyyYacfU_To : $@convention(thin) @Sendable @async (NSString, Optional<@convention(block) @Sendable (Optional<NSString>, Optional<NSError>) -> ()>, SlowServerlet) -> () {
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[STR_ARG:%.*]] = begin_borrow {{.*}} : $String
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK: apply [[NATIVE]]([[STR_ARG]], [[SELF]])
// CHECK-C: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C: apply [[NATIVE]]([[STR_ARG]], [[SELF]])
// CHECK-NN: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NN: apply [[NATIVE]]([[ACTOR]], [[STR_ARG]], [[SELF]])
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingDangerousNullablyyS2SYaKFyyYacfU_To'
override func doSomethingDangerousNullably(_ x: String) async throws -> String {
return x
@@ -167,17 +206,25 @@ class SlowServerlet: SlowServer {
// Native
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF'
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error) {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF'
// @objc closure thunk
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKFyyYacfU_To : $@convention(thin) @Sendable @async (Optional<@convention(block) @Sendable (Optional<NSString>, Optional<NSError>) -> ()>, SlowServerlet) -> () {
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK: apply [[NATIVE]]([[SELF]])
// CHECK-C: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C: try_apply [[NATIVE]]([[SELF]])
// CHECK-NN: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NN: try_apply [[NATIVE]]([[ACTOR]], [[SELF]])
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC30doSomethingUnspecifiedNullablySSyYaKFyyYacfU_To'
override func doSomethingUnspecifiedNullably() async throws -> String {
fatalError()
@@ -185,20 +232,31 @@ class SlowServerlet: SlowServer {
// Native
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF'
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error) {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF'
// @objc thunk closure
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKFyyYacfU_To : $@convention(thin) @Sendable @async (@convention(block) @Sendable ({{.*}}, Optional<NSString>, Optional<NSError>) -> (), SlowServerlet) -> () {
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK-C: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NN: try_apply [[NATIVE]]([[ACTOR]], [[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// CHECK: [[NORMAL_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}0
// CHECK: integer_literal {{.*}}0
//
// CHECK: [[ERROR_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}1
// CHECK: integer_literal {{.*}}1
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC17doSomethingFlaggySSyYaKFyyYacfU_To'
override func doSomethingFlaggy() async throws -> String {
return ""
@@ -206,39 +264,59 @@ class SlowServerlet: SlowServer {
// Native
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF'
//
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error) {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF'
//
// @objc thunk closure
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKFyyYacfU_To : $@convention(thin) @Sendable @async (@convention(block) @Sendable (Optional<NSString>, {{.*}}, Optional<NSError>) -> (), SlowServerlet) -> () {
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK-C: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-C: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC21doSomethingZeroFlaggySSyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @error any Error)
// CHECK-NN: try_apply [[NATIVE]]([[ACTOR]], [[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// CHECK: [[NORMAL_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}1
// CHECK: integer_literal {{.*}}1
//
// CHECK: [[ERROR_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}0
// CHECK: integer_literal {{.*}}0
override func doSomethingZeroFlaggy() async throws -> String {
return ""
}
// Native
//
// CHECK-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error)
// CHECK-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-NEXT: hop_to_executor [[ACTOR]]
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF'
// CHECK-C-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error)
// CHECK-C-NOT: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-C: [[ACTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C-NEXT: hop_to_executor [[ACTOR]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF'
//
// CHECK-NN-LABEL: sil hidden [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error) {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>,
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF'
//
// CHECK-LABEL: sil shared [thunk] [ossa] @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKFyyYacfU_To : $@convention(thin) @Sendable @async (@convention(block) @Sendable ({{.*}}, Optional<NSString>, Optional<NSError>, Optional<NSString>) -> (), SlowServerlet) -> () {
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error)
// CHECK: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[ACTOR:%.*]] = enum $Optional<any Actor>, #Optional.none!enumelt
// CHECK: [[SELF:%.*]] = begin_borrow {{.*}} : $SlowServerlet
// CHECK-C: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error)
// CHECK-C: try_apply [[NATIVE]]([[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
// CHECK-NN: [[NATIVE:%.*]] = function_ref @$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed SlowServerlet) -> (@owned String, @owned String, @error any Error)
// CHECK-NN: try_apply [[NATIVE]]([[ACTOR]], [[SELF]]) : {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// CHECK: [[NORMAL_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}1
//
// CHECK: [[ERROR_BB]]({{.*}}):
// CHECK: integer_literal {{.*}}0
// CHECK: } // end sil function '$s21objc_async_from_swift13SlowServerletC28doSomethingMultiResultFlaggySS_SStyYaKFyyYacfU_To'
@@ -294,3 +372,222 @@ actor Dril: NSObject {
return true
}
}
// Check that we do not crash here and emit the autoclosures correctly
func testAutoclosureInStaticMethod() {
final class TestKlass {
// Default argument for method.
//
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_ : $@convention(thin) () -> @owned @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error) {
//
// Get standard.
// CHECK: [[METATYPE:%.*]] = metatype $@objc_metatype SlowServer.Type
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method %1 : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
// CHECK: [[STANDARD:%.*]] = apply [[GET_STANDARD_FUNC]]([[METATYPE]])
//
// Then grab value.
// CHECK: [[GET_VALUE:%.*]] = function_ref @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_ : $@convention(thin) (@guaranteed SlowServer) -> @owned @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error)
// CHECK: [[RESULT:%.*]] = apply [[GET_VALUE]]([[STANDARD]])
//
// Then we need to thunk to eliminate the implicit leading parameter. We use
// the thunk that passes in .none so this acts as a concurrent function.
//
// CHECK: [[THUNK_FN:%.*]] = function_ref @$sScA_pSgS2Ss5Error_pIegHggozo_S2SsAB_pIegHgozo_TR : $@convention(thin) @async (@guaranteed String, @guaranteed @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error)) -> (@owned String, @error any Error)
// CHECK: [[THUNKED:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[RESULT]])
// CHECK: return [[THUNKED]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_'
// This is the first implicit closure. We close over self here.
//
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_ : $@convention(thin) (@guaranteed SlowServer) -> @owned @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String) -> (@owned String, @error any Error) {
// CHECK: bb0([[SELF:%.*]] :
//
// Close over self and return it.
// CHECK: [[SECOND_CLOSURE:%.*]] = function_ref @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_S2SYaKYCcfu0_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServer) -> (@owned String, @error any Error)
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CLOSE_OVER_SELF:%.*]] = partial_apply [callee_guaranteed] [[SECOND_CLOSURE]]([[SELF_COPY]])
// CHECK: return [[CLOSE_OVER_SELF]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_'
// The second closure. In this function we actually perform the objective-c call.
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_S2SYaKYCcfu0_ : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed SlowServer) -> (@owned String, @error any Error) {
// CHECK: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>, [[ARG:%.*]] : @guaranteed $String, [[CAPTURE:%.*]] : @closureCapture @guaranteed $SlowServer):
//
// Hop to the actor
// CHECK: hop_to_executor [[ACTOR]]
//
// Declare result
// CHECK: [[RESULT:%.*]] = alloc_stack $String
//
// Bridge string arg.
// CHECK: [[ARG_C:%.*]] = copy_value [[ARG]]
// CHECK: [[BRIDGE_FN:%.*]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
// CHECK: [[ARG_C_B:%.*]] = begin_borrow [[ARG_C]]
// CHECK: [[NS_STRING:%.*]] = apply [[BRIDGE_FN]]([[ARG_C_B]])
//
// ObjC Method
// CHECK: [[OBJC_METHOD:%.*]] = objc_method [[CAPTURE]]
//
// Prepare the continuation.
// CHECK: [[RAW_UNSAFE_CONT:%.*]] = get_async_continuation_addr [throws] String, [[RESULT]]
// CHECK: [[UNSAFE_CONT:%.*]] = struct $UnsafeContinuation<String, any Error> ([[RAW_UNSAFE_CONT]] :
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage Any
// CHECK: [[PROJ_BLOCK_STORAGE:%.*]] = project_block_storage [[BLOCK_STORAGE]]
// CHECK: [[INIT_PROJ_BLOCK_STORAGE:%.*]] = init_existential_addr [[PROJ_BLOCK_STORAGE]]
// CHECK: store [[UNSAFE_CONT]] to [trivial] [[INIT_PROJ_BLOCK_STORAGE]]
// CHECK: merge_isolation_region [[BLOCK_STORAGE]] : $*@block_storage Any, [[RESULT]]
// CHECK: [[OBJC_COMPLETION_HANDLER_IMPL:%.*]] = function_ref @$sSo8NSStringCSgSo7NSErrorCSgIeyBhyy_SSTz_ : $@convention(c) @Sendable (@inout_aliasable @block_storage Any, Optional<NSString>, Optional<NSError>) -> ()
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] : $*@block_storage Any, invoke [[OBJC_COMPLETION_HANDLER_IMPL]]
// CHECK: merge_isolation_region [[CAPTURE]] : $SlowServer, [[BLOCK_STORAGE]]
// CHECK: apply [[OBJC_METHOD]]([[NS_STRING]], [[BLOCK]], [[CAPTURE]])
// CHECK: await_async_continuation [[RAW_UNSAFE_CONT]] : $Builtin.RawUnsafeContinuation, resume [[RESUME_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// CHECK: [[RESUME_BB]]:
// CHECK: hop_to_executor [[ACTOR]]
// CHECK: [[LOADED_RESULT:%.*]] = load [take] [[RESULT]]
// CHECK: return [[LOADED_RESULT]]
//
// CHECK: [[ERROR_BB]]([[ERROR:%.*]] :
// CHECK: hop_to_executor [[ACTOR]]
// CHECK: throw [[ERROR]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKYCcSo10SlowServerCcfu_S2SYaKYCcfu0_'
// Actual static method
//
// We do not actually care about FileChecking this... we just need to
// FileCheck the hop_to_executor to show to FileCheck that we expect these
// hop_to_executor lines to occur in the function since we reject
// non-explicitly specified hop_to_executor lines.
//
// CHECK-C-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ : $@convention(method) @async (@guaranteed String, @guaranteed @noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), @thick TestKlass.Type) -> @owned Optional<String> {
// CHECK-C: bb0([[STRING:%.*]] : @guaranteed $String, [[COMPLETION:%.*]] : @guaranteed $@noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), [[METATYPE:%.*]] : $@thick TestKlass.Type)
// CHECK-C: [[EXEC_NONE:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ'
//
// CHECK-NN-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed @noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), @thick TestKlass.Type) -> @owned Optional<String> {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>, [[STRING:%.*]] : @guaranteed $String, [[COMPLETION:%.*]] : @guaranteed $@noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), [[METATYPE:%.*]] : $@thick TestKlass.Type)
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C8getValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ'
static func getValue(id: String,
valueForKey: (_ identifier: String) async throws -> String = SlowServer.standard.value(withKey:)) async -> String? {
let result: String
do {
result = try await valueForKey(id)
} catch {
return nil
}
return result
}
// Default argument for method.
//
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_ : $@convention(thin) () -> @owned @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error) {
//
// Get standard.
// CHECK: [[METATYPE:%.*]] = metatype $@objc_metatype SlowServer.Type
// CHECK: [[GET_STANDARD_FUNC:%.*]] = objc_method %1 : $@objc_metatype SlowServer.Type, #SlowServer.standard!getter.foreign : (SlowServer.Type) -> () -> SlowServer, $@convention(objc_method) (@objc_metatype SlowServer.Type) -> @autoreleased SlowServer
// CHECK: [[STANDARD:%.*]] = apply [[GET_STANDARD_FUNC]]([[METATYPE]])
//
// Then grab value.
// CHECK: [[GET_VALUE:%.*]] = function_ref @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_ : $@convention(thin) (@guaranteed SlowServer) -> @owned @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error)
// CHECK: [[RESULT:%.*]] = apply [[GET_VALUE]]([[STANDARD]])
//
// CHECK: return [[RESULT]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_'
// This is the first implicit closure. We close over self here.
//
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_ : $@convention(thin) (@guaranteed SlowServer) -> @owned @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error) {
// CHECK: bb0([[SELF:%.*]] :
//
// Close over self and return it.
// CHECK: [[SECOND_CLOSURE:%.*]] = function_ref @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_S2SYaKScMYccfu0_ : $@convention(thin) @async (@guaranteed String, @guaranteed SlowServer) -> (@owned String, @error any Error)
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CLOSE_OVER_SELF:%.*]] = partial_apply [callee_guaranteed] [[SECOND_CLOSURE]]([[SELF_COPY]])
// CHECK: return [[CLOSE_OVER_SELF]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_'
// The second closure. In this function we actually perform the objective-c call.
//
// It is main actor isolated.
//
// CHECK-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_S2SYaKScMYccfu0_ : $@convention(thin) @async (@guaranteed String, @guaranteed SlowServer) -> (@owned String, @error any Error) {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $String, [[CAPTURE:%.*]] : @closureCapture @guaranteed $SlowServer):
//
// CHECK: [[ACTOR:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thick MainActor.Type) -> @owned MainActor
//
// Hop to the actor
// CHECK: [[ACTOR_B:%.*]] = begin_borrow [[ACTOR]]
// CHECK: hop_to_executor [[ACTOR_B]]
//
// Declare result
// CHECK: [[RESULT:%.*]] = alloc_stack $String
//
// Bridge string arg.
// CHECK: [[ARG_C:%.*]] = copy_value [[ARG]]
// CHECK: [[BRIDGE_FN:%.*]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
// CHECK: [[ARG_C_B:%.*]] = begin_borrow [[ARG_C]]
// CHECK: [[NS_STRING:%.*]] = apply [[BRIDGE_FN]]([[ARG_C_B]])
//
// ObjC Method
// CHECK: [[OBJC_METHOD:%.*]] = objc_method [[CAPTURE]]
//
// Prepare the continuation.
// CHECK: [[RAW_UNSAFE_CONT:%.*]] = get_async_continuation_addr [throws] String, [[RESULT]]
// CHECK: [[UNSAFE_CONT:%.*]] = struct $UnsafeContinuation<String, any Error> ([[RAW_UNSAFE_CONT]] :
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage Any
// CHECK: [[PROJ_BLOCK_STORAGE:%.*]] = project_block_storage [[BLOCK_STORAGE]]
// CHECK: [[INIT_PROJ_BLOCK_STORAGE:%.*]] = init_existential_addr [[PROJ_BLOCK_STORAGE]]
// CHECK: store [[UNSAFE_CONT]] to [trivial] [[INIT_PROJ_BLOCK_STORAGE]]
// CHECK: merge_isolation_region [[BLOCK_STORAGE]] : $*@block_storage Any, [[RESULT]]
// CHECK: [[OBJC_COMPLETION_HANDLER_IMPL:%.*]] = function_ref @$sSo8NSStringCSgSo7NSErrorCSgIeyBhyy_SSTz_ : $@convention(c) @Sendable (@inout_aliasable @block_storage Any, Optional<NSString>, Optional<NSError>) -> ()
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] : $*@block_storage Any, invoke [[OBJC_COMPLETION_HANDLER_IMPL]]
// CHECK: merge_isolation_region [[CAPTURE]] : $SlowServer, [[BLOCK_STORAGE]]
// CHECK: apply [[OBJC_METHOD]]([[NS_STRING]], [[BLOCK]], [[CAPTURE]])
// CHECK: await_async_continuation [[RAW_UNSAFE_CONT]] : $Builtin.RawUnsafeContinuation, resume [[RESUME_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// CHECK: [[RESUME_BB]]:
// CHECK: hop_to_executor [[ACTOR_B]]
// CHECK: [[LOADED_RESULT:%.*]] = load [take] [[RESULT]]
// CHECK: return [[LOADED_RESULT]]
//
// CHECK: [[ERROR_BB]]([[ERROR:%.*]] :
// CHECK: hop_to_executor [[ACTOR_B]]
// CHECK: throw [[ERROR]]
// CHECK: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZfA0_S2SYaKScMYccSo10SlowServerCcfu_S2SYaKScMYccfu0_'
// Actual static method
//
// This is not main actor isolated
//
// CHECK-C-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ : $@convention(method) @async (@guaranteed String, @guaranteed @noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), @thick TestKlass.Type) -> @owned Optional<String> {
// CHECK-C: bb0([[STRING:%.*]] : @guaranteed $String, [[COMPLETION:%.*]] : @guaranteed $@noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), [[METATYPE:%.*]] : $@thick TestKlass.Type)
// CHECK-C: [[EXEC_NONE:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none!enumelt
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: hop_to_executor [[EXEC_NONE]]
// CHECK-C: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ'
//
// CHECK-NN-LABEL: sil private [ossa] @$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, @guaranteed String, @guaranteed @noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), @thick TestKlass.Type) -> @owned Optional<String> {
// CHECK-NN: bb0([[ACTOR:%.*]] : @guaranteed $Optional<any Actor>, [[STRING:%.*]] : @guaranteed $String, [[COMPLETION:%.*]] : @guaranteed $@noescape @async @callee_guaranteed (@guaranteed String) -> (@owned String, @error any Error), [[METATYPE:%.*]] : $@thick TestKlass.Type)
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: hop_to_executor [[ACTOR]]
// CHECK-NN: } // end sil function '$s21objc_async_from_swift29testAutoclosureInStaticMethodyyF9TestKlassL_C17getMainActorValue2id11valueForKeySSSgSS_S2SYaKXEtYaFZ'
static func getMainActorValue(id: String,
valueForKey: (_ identifier: String) async throws -> String = SlowServer.standard.mainActorValue(withKey:)) async -> String? {
let result: String
do {
result = try await valueForKey(id)
} catch {
return nil
}
return result
}
}
}