1+ // RUN: %target-swift-frontend -O -primary-file %s -emit-sil -enable-experimental-distributed | %FileCheck %s --dump-input=fail
2+
3+ import _Distributed
4+
5+ class SomeClass { }
6+
7+ @available ( SwiftStdlib 5 . 5 , * )
8+ actor SimpleActor {
9+ let someFieldInLocalActor : SomeClass
10+ init ( field: SomeClass ) {
11+ self . someFieldInLocalActor = field
12+ }
13+ }
14+
15+
16+ @available ( SwiftStdlib 5 . 5 , * )
17+ distributed actor SimpleEmptyDistributedActor {
18+ let localOnlyField : SomeClass
19+
20+ init ( field: SomeClass , transport: ActorTransport ) {
21+ self . localOnlyField = field
22+ }
23+ }
24+
25+ // ==== ------------------------------------------------------------------------
26+ // ==== Check that a normal local only actor is left unchanged
27+
28+ // CHECK: // SimpleActor.deinit
29+ // CHECK: sil hidden{{.*}} @$s35distributed_actor_remote_deinit_sil11SimpleActorCfd : $@convention(method) (@guaranteed SimpleActor) -> @owned Builtin.NativeObject {
30+ // CHECK: // %0 "self" // users: %6, %5, %2, %1
31+ // CHECK: bb0(%0 : $SimpleActor):
32+ // CHECK: debug_value %0 : $SimpleActor, let, name "self", argno 1, implicit // id: %1
33+ // CHECK: %2 = ref_element_addr %0 : $SimpleActor, #SimpleActor.someFieldInLocalActor // user: %3
34+ // CHECK: %3 = load %2 : $*SomeClass // user: %4
35+ // CHECK: strong_release %3 : $SomeClass // id: %4
36+ // CHECK: %5 = builtin "destroyDefaultActor"(%0 : $SimpleActor) : $()
37+ // CHECK: %6 = unchecked_ref_cast %0 : $SimpleActor to $Builtin.NativeObject // user: %7
38+ // CHECK: return %6 : $Builtin.NativeObject // id: %7
39+ // CHECK: } // end sil function '$s35distributed_actor_remote_deinit_sil11SimpleActorCfd'
40+
41+
42+
43+
44+ // ==== deinit must have the extra "if remote..." path emitted for the
45+ // distributed actor only. That path will not attempt deallocating the
46+ // `localOnly...` fields, since they were never initialized and have no storage.
47+
48+ // CHECK: // SimpleEmptyDistributedActor.deinit
49+ // sil hidden [available 12.0] @$s35distributed_actor_remote_deinit_sil27SimpleEmptyDistributedActorCfd : $@convention(method) (@guaranteed SimpleEmptyDistributedActor) -> @owned Builtin.NativeObject {
50+ // CHECK: // [[SELF:%[0-9]+]] "self"
51+ // CHECK: bb0(%0 : $SimpleEmptyDistributedActor):
52+ // CHECK: debug_value [[SELF]] : $SimpleEmptyDistributedActor, let, name "self", argno 1, implicit
53+ // CHECK: [[IDENTITY_ADDR:%[0-9]+]] = ref_element_addr %0 : $SimpleEmptyDistributedActor, #SimpleEmptyDistributedActor.id // users: %13, %24
54+ // CHECK: [[TRANSPORT_ADDR:%[0-9]+]] = ref_element_addr %0 : $SimpleEmptyDistributedActor, #SimpleEmptyDistributedActor.actorTransport
55+ // CHECK: [[SELF_1:%[0-9]+]] = init_existential_ref %0 : $SimpleEmptyDistributedActor : $SimpleEmptyDistributedActor, $AnyObject
56+ // CHECK: // function_ref swift_distributed_actor_is_remote
57+ // CHECK: [[IS_REMOTE_FN_1:%[0-9]+]] = function_ref @swift_distributed_actor_is_remote : $@convention(thin) (@guaranteed AnyObject) -> Bool
58+ // CHECK: [[IS_REMOTE_FN_RES_1:%[0-9]+]] = apply [[IS_REMOTE_FN_1]]([[SELF_1]]) : $@convention(thin) (@guaranteed AnyObject) -> Bool
59+ // CHECK: [[IS_REMOTE_BOOL_1:%[0-9]+]] = struct_extract [[IS_REMOTE_FN_RES_1]] : $Bool, #Bool._value
60+ // CHECK: cond_br [[IS_REMOTE_BOOL_1]], [[BB_CONT_1:bb[0-9]+]], [[BB_RESIGN_DIST_IDENTITY:bb[0-9]+]]
61+
62+ // CHECK: [[BB_CONT_1]]:
63+ // CHECK: br [[BB_CHECK_REMOTE_OR_LOCAL_MEMBER_DEINIT_TYPE:bb[0-9]+]]
64+
65+ // It was a local actor, so we resign the address:
66+ // CHECK: [[BB_RESIGN_DIST_IDENTITY]]:
67+ // %11 = open_existential_addr immutable_access %4 : $*ActorTransport to $*@opened({{.*}}) ActorTransport // users: %13, %13, %12
68+ // CHECK: [[RESIGN_FN:%[0-9]+]] = witness_method $@opened({{.*}}) ActorTransport, #ActorTransport.resignIdentity
69+ // CHECK: [[RESIGNED:%[0-9]+]] = apply [[RESIGN_FN]]<@opened({{.*}}) ActorTransport>(%3, %11) : $@convention(witness_method: ActorTransport) <τ_0_0 where τ_0_0 : ActorTransport> (@in_guaranteed AnyActorIdentity, @in_guaranteed τ_0_0) -> ()
70+ // CHECK: br [[BB_CHECK_REMOTE_OR_LOCAL_MEMBER_DEINIT_TYPE]]
71+
72+ // Check if we must skip destroying local storage because actor was remote
73+ // CHECK: [[BB_CHECK_REMOTE_OR_LOCAL_MEMBER_DEINIT_TYPE]]:
74+ // CHECK: %15 = init_existential_ref %0 : $SimpleEmptyDistributedActor : $SimpleEmptyDistributedActor, $AnyObject
75+ // CHECK: %16 = apply %6(%15) : $@convention(thin) (@guaranteed AnyObject) -> Bool
76+ // CHECK: %17 = struct_extract %16 : $Bool, #Bool._value // user: %18
77+ // CHECK: cond_br %17, [[BB_CONT_REMOTE_DONT_DESTROY_LOCAL_MEMBERS:bb[0-9]+]], [[BB_CONT_DESTROY_LOCAL_THEN_INDEPENDENT_MEMBERS:bb[0-9]+]]
78+
79+ // CHECK: [[BB_CONT_REMOTE_DONT_DESTROY_LOCAL_MEMBERS]]:
80+ // CHECK: br [[BB_DESTROY_INDEPENDENT_MEMBERS:bb[0-9]+]]
81+
82+ // We were a local instance after all, and thus must destroy local properties
83+ // CHECK: [[BB_CONT_DESTROY_LOCAL_THEN_INDEPENDENT_MEMBERS]]:
84+ // CHECK: [[FIELD_ADDR:%[0-9]+]] = ref_element_addr %0 : $SimpleEmptyDistributedActor, #SimpleEmptyDistributedActor.localOnlyField
85+ // CHECK: [[LOAD_FIELD_ADDR:%[0-9]+]] = load [[FIELD_ADDR]] : $*SomeClass
86+ // CHECK: strong_release [[LOAD_FIELD_ADDR]] : $SomeClass
87+ // CHECK: br [[BB_DESTROY_INDEPENDENT_MEMBERS]]
88+
89+ // Destroy "distributed nonisolated" fields and the actor itself
90+ // CHECK: [[BB_DESTROY_INDEPENDENT_MEMBERS]]:
91+ // CHECK: destroy_addr [[IDENTITY_ADDR]] : $*AnyActorIdentity
92+ // CHECK: destroy_addr [[TRANSPORT_ADDR]] : $*ActorTransport
93+ // CHECK: {{.*}} = builtin "destroyDefaultActor"(%0 : $SimpleEmptyDistributedActor) : $()
94+ // CHECK: dealloc_ref [[SELF]] : $SimpleEmptyDistributedActor
95+ // CHECK: [[EMPTY:%[0-9]+]] = tuple ()
96+ // CHECK: return [[EMPTY]] : $()
97+ // } // end sil function '$s35distributed_actor_remote_deinit_sil27SimpleEmptyDistributedActorCfD'
0 commit comments