// RUN: %target-swift-emit-silgen -swift-version 6 -enable-experimental-feature AsyncCallerExecution %s | %FileCheck %s // REQUIRES: concurrency // REQUIRES: asserts // REQUIRES: swift_feature_AsyncCallerExecution //===----------------------------------------------------------------------===// // MARK: Declarations //===----------------------------------------------------------------------===// class NonSendableKlass {} func unspecifiedSyncUse(_ t: NonSendableKlass) {} func unspecifiedAsyncUse(_ t: NonSendableKlass) async {} //===----------------------------------------------------------------------===// // MARK: Tests //===----------------------------------------------------------------------===// // CHECK-LABEL: // nonisolatedAsync() // CHECK-NEXT: Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation0A5AsyncyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> () { // CHECK: bb0([[ACTOR:%.*]] : @guaranteed $Optional): // CHECK: hop_to_executor [[ACTOR]] // CHECK: } // end sil function '$s30nonisolated_inherits_isolation0A5AsyncyyYaF' nonisolated func nonisolatedAsync() async {} func unspecifiedAsyncCallee() async {} // CHECK-LABEL: // unspecifiedAsync() // CHECK-NEXT: Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation16unspecifiedAsyncyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> () { // CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional): // CHECK: hop_to_executor [[ACTOR]] // CHECK: [[FUNC_REF:%.*]] = function_ref @$s30nonisolated_inherits_isolation22unspecifiedAsyncCalleeyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> () // CHECK: apply [[FUNC_REF]]([[ACTOR]]) // CHECK: hop_to_executor [[ACTOR]] // CHECK: } // end sil function '$s30nonisolated_inherits_isolation16unspecifiedAsyncyyYaF' func unspecifiedAsync() async { await unspecifiedAsyncCallee() } struct NonisolatedStruct { // Do not apply it to sync initializers. // // CHECK-LABEL: // NonisolatedStruct.init(sync:) // CHECK-NEXT: // Isolation: unspecified // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation17NonisolatedStructV4syncACyt_tcfC : $@convention(method) (@thin NonisolatedStruct.Type) -> NonisolatedStruct { // CHECK: } // end sil function '$s30nonisolated_inherits_isolation17NonisolatedStructV4syncACyt_tcfC' init(sync: ()) {} // Do apply it to sync initializers. // // CHECK-LABEL: // NonisolatedStruct.init(asynchronous:) // CHECK-NEXT: // Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation17NonisolatedStructV12asynchronousACyt_tYacfC : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @thin NonisolatedStruct.Type) -> NonisolatedStruct { // CHECK: } // end sil function '$s30nonisolated_inherits_isolation17NonisolatedStructV12asynchronousACyt_tYacfC' init(asynchronous: ()) async {} // Do not apply it to non-async methods. These do not require any changes. func syncMethod() {} // But do apply it to async methods. // CHECK-LABEL: // NonisolatedStruct.asyncMethod() // CHECK-NEXT: // Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation17NonisolatedStructV11asyncMethodyyYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, NonisolatedStruct) -> () { // CHECK: } // end sil function '$s30nonisolated_inherits_isolation17NonisolatedStructV11asyncMethodyyYaF' func asyncMethod() async {} } // CHECK-LABEL: // useNonisolatedStruct() // CHECK-NEXT: // Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation20useNonisolatedStructyyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> () { // CHECK: bb0([[ACTOR:%.*]] : // CHECK: hop_to_executor [[ACTOR]] // CHECK: [[VALUE:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thin NonisolatedStruct.Type) -> NonisolatedStruct // CHECK: [[VAR_DECL:%.*]] = move_value [var_decl] [[VALUE]] // CHECK: [[ASYNC_CALL:%.*]] = function_ref @$s30nonisolated_inherits_isolation17NonisolatedStructV11asyncMethodyyYaF : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, NonisolatedStruct) -> () // CHECK: apply [[ASYNC_CALL]]([[ACTOR]], [[VAR_DECL]]) // CHECK: hop_to_executor [[ACTOR]] // CHECK: extend_lifetime [[VAR_DECL]] // CHECK: } // end sil function '$s30nonisolated_inherits_isolation20useNonisolatedStructyyYaF' func useNonisolatedStruct() async { // Should be disconnected. let x = NonisolatedStruct(sync: ()) // When we call the async method, we should pass in the implicit parameter. await x.asyncMethod() } // CHECK-LABEL: // useNonisolatedStruct2() // CHECK-NEXT: // Isolation: caller_isolation_inheriting // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation21useNonisolatedStruct2yyYaF : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional) -> () { // CHECK: bb0([[ACTOR:%.*]] : // CHECK: hop_to_executor [[ACTOR]] // CHECK: [[VALUE:%.*]] = apply {{%.*}}([[ACTOR]], {{%.*}}) : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @thin NonisolatedStruct.Type) -> NonisolatedStruct // CHECK: hop_to_executor [[ACTOR]] // CHECK: [[VAR_DECL:%.*]] = move_value [var_decl] [[VALUE]] // CHECK: apply {{%.*}}([[ACTOR]], [[VAR_DECL]]) : $@convention(method) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, NonisolatedStruct) -> () // CHECK: hop_to_executor [[ACTOR]] // CHECK: extend_lifetime [[VAR_DECL]] // CHECK: } // end sil function '$s30nonisolated_inherits_isolation21useNonisolatedStruct2yyYaF' func useNonisolatedStruct2() async { let x = await NonisolatedStruct(asynchronous: ()) // When we call the async method, we should pass in the implicit parameter. await x.asyncMethod() } // Make sure that we handle global actor isolated functions without adding the // implicit parameter convention. // // CHECK-LABEL: // mainActorSync() // CHECK-NEXT: // Isolation: global_actor. type: MainActor // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation13mainActorSyncyyF : $@convention(thin) () -> () { // CHECK: } // end sil function '$s30nonisolated_inherits_isolation13mainActorSyncyyF' @MainActor func mainActorSync() {} // CHECK-LABEL: // mainActorAsync() // CHECK-NEXT: // Isolation: global_actor. type: MainActor // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation14mainActorAsyncyyYaF : $@convention(thin) @async () -> () { // CHECK: } // end sil function '$s30nonisolated_inherits_isolation14mainActorAsyncyyYaF' @MainActor func mainActorAsync() async {} @MainActor class MainActorKlass { var ns = NonSendableKlass() // CHECK-LABEL: // MainActorKlass.callNonIsolatedWithParam() // CHECK-NEXT: // Isolation: global_actor. type: MainActor // CHECK-NEXT: sil hidden [ossa] @$s30nonisolated_inherits_isolation14MainActorKlassC24callNonIsolatedWithParamyyYaF : $@convention(method) @async (@guaranteed MainActorKlass) -> () { // CHECK: bb0( // CHECK: [[ACTOR:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thick MainActor.Type) -> @owned MainActor // CHECK: [[B_ACTOR:%.*]] = begin_borrow [[ACTOR]] // CHECK: hop_to_executor [[B_ACTOR]] // CHECK: [[VAR_DECL:%.*]] = move_value [lexical] [var_decl] // CHECK: [[B_VAR_DECL:%.*]] = begin_borrow [[VAR_DECL]] // Sync call // CHECK: apply {{%.*}}([[B_VAR_DECL]]) : $@convention(thin) (@guaranteed NonSendableKlass) -> () // CHECK: [[B_VAR_DECL_2:%.*]] = begin_borrow [[VAR_DECL]] // Async call with marshaling to wrap the actor in Optional // CHECK: [[B_ACTOR_COPY:%.*]] = copy_value [[B_ACTOR]] // CHECK: [[B_ACTOR_COPY_EX:%.*]] = init_existential_ref [[B_ACTOR_COPY]] : $MainActor // CHECK: [[B_ACTOR_COPY_EX_OPT:%.*]] = enum $Optional, #Optional.some!enumelt, [[B_ACTOR_COPY_EX]] // CHECK: apply {{%.*}}([[B_ACTOR_COPY_EX_OPT]], [[B_VAR_DECL_2]]) : $@convention(thin) @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional, @guaranteed NonSendableKlass) -> () // CHECK: hop_to_executor [[B_ACTOR]] // CHECK: } // end sil function '$s30nonisolated_inherits_isolation14MainActorKlassC24callNonIsolatedWithParamyyYaF' func callNonIsolatedWithParam() async { let n = ns unspecifiedSyncUse(n) await unspecifiedAsyncUse(n) } }