@@ -7,6 +7,8 @@ func invokedDeinit() {}
77 case some( File )
88 case none
99
10+ deinit { }
11+
1012 // NOTE: we can't pattern match on self since
1113 // that would consume it before we can forget self!
1214 var test : Int {
@@ -60,71 +62,55 @@ func invokedDeinit() {}
6062}
6163
6264@_moveOnly struct PointerTree {
63- let left : Ptr
64- let file : File
65- let popularity : Int
66- var right : Ptr
67-
68- init ( doForget: Bool , file: __owned File, ptr: Ptr ) throws {
69- self . file = file
70- self . left = ptr
71- self . popularity = 0
72- self . right = ptr
65+ let left : UnsafePointer < UInt > ?
66+ let file : Int = 0
67+ lazy var popularity : Int = 0
68+ var right : Float = 0.0
7369
70+ consuming func tryDestroy( doForget: Bool ) throws {
7471 if doForget {
7572 _forget self
7673 }
7774 throw E . err
7875 }
7976
80- // CHECK-LABEL: sil hidden [ossa] @$s4test11PointerTreeV8doForget4file3ptrACSb_AA4FileVnAA3PtrCtKcfC
77+ // CHECK-LABEL: sil hidden [ossa] @$s4test11PointerTreeV10tryDestroy8doForgetySb_tKF : $@convention(method) (Bool, @owned PointerTree) -> @error any Error {
8178// CHECK: bb0{{.*}}:
8279// CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var PointerTree }, var, name "self"
83- // CHECK: [[MUI:%.*]] = mark_uninitialized [rootself] [[SELF_BOX]] : ${ var PointerTree }
84- // CHECK: [[SELF:%.*]] = begin_borrow [lexical] [[MUI]] : ${ var PointerTree }
85- // CHECK: [[SELF_PTR:%.*]] = project_box [[SELF]] : ${ var PointerTree }, 0
80+ // CHECK: [[SELF_PTR:%.*]] = project_box [[SELF_BOX]] : ${ var PointerTree }, 0
8681// .. skip to the conditional test ..
87- // CHECK: [[SHOULD_THROW :%.*]] = struct_extract {{.*}} : $Bool, #Bool._value
88- // CHECK: cond_br [[SHOULD_THROW ]], bb1, bb2
82+ // CHECK: [[SHOULD_FORGET :%.*]] = struct_extract {{.*}} : $Bool, #Bool._value
83+ // CHECK: cond_br [[SHOULD_FORGET ]], bb1, bb2
8984//
9085// CHECK: bb1:
9186// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[SELF_PTR]] : $*PointerTree
9287// CHECK: [[MMC:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] : $*PointerTree
9388// CHECK: [[COPIED_SELF:%.*]] = load [copy] [[MMC]] : $*PointerTree
9489// CHECK: end_access [[ACCESS]] : $*PointerTree
9590// CHECK: [[DD:%.*]] = drop_deinit [[COPIED_SELF]]
96- // CHECK: ([[LEFT:%.*]], [[FILE:%.*]], {{%.*}}, [[RIGHT:%.*]]) = destructure_struct [[DD]] : $PointerTree
97- // CHECK: destroy_value [[LEFT]] : $Ptr
98- // CHECK: destroy_value [[FILE]] : $File
99- // CHECK: destroy_value [[RIGHT]] : $Ptr
91+ // CHECK: end_lifetime [[DD]]
10092// CHECK: br bb3
10193//
10294// CHECK: bb2:
10395// CHECK: br bb3
10496//
10597// CHECK: bb3:
106- // CHECK: end_borrow [[SELF]] : ${ var PointerTree }
107- // CHECK: destroy_value [[MUI]] : ${ var PointerTree }
98+ // CHECK: destroy_value [[SELF_BOX]] : ${ var PointerTree }
10899// CHECK: throw
109100// CHECK: } // end sil function
110101
111102// After the mandatory passes have run, check for correct deinitializations within the init.
112103
113- // CHECK-SIL-LABEL: sil hidden @$s4test11PointerTreeV8doForget4file3ptrACSb_AA4FileVnAA3PtrCtKcfC
114- // CHECK-SIL: [[SHOULD_THROW :%.*]] = struct_extract {{.*}} : $Bool, #Bool._value
115- // CHECK-SIL: cond_br [[SHOULD_THROW ]], bb1, bb2
104+ // CHECK-SIL-LABEL: sil hidden @$s4test11PointerTreeV10tryDestroy8doForgetySb_tKF
105+ // CHECK-SIL: [[SHOULD_FORGET :%.*]] = struct_extract {{.*}} : $Bool, #Bool._value
106+ // CHECK-SIL: cond_br [[SHOULD_FORGET ]], bb1, bb2
116107//
117108// CHECK-SIL: bb1:
118109// CHECK-SIL: [[ACCESS:%.*]] = begin_access [modify] [static] {{.*}} : $*PointerTree
119110// CHECK-SIL: [[SELF_VAL:%.*]] = load [[ACCESS]] : $*PointerTree
120111// CHECK-SIL: end_access [[ACCESS]] : $*PointerTree
121- // CHECK-SIL: [[LEFT:%.*]] = struct_extract [[SELF_VAL]] : $PointerTree, #PointerTree.left
122- // CHECK-SIL: [[FILE:%.*]] = struct_extract [[SELF_VAL]] : $PointerTree, #PointerTree.file
123- // CHECK-SIL: [[RIGHT:%.*]] = struct_extract [[SELF_VAL]] : $PointerTree, #PointerTree.right
124- // CHECK-SIL: strong_release [[LEFT]] : $Ptr
125- // CHECK-SIL: [[FILE_DEINIT:%.*]] = function_ref @$s4test4FileVfD : $@convention(method) (@owned File) -> ()
126- // CHECK-SIL: apply [[FILE_DEINIT]]([[FILE]])
127- // CHECK-SIL: strong_release [[RIGHT]] : $Ptr
112+ // CHECK-SIL-NOT: struct_extract
113+ // no accesses to the fields are expected because the fields are no-op destroyed.
128114// CHECK-SIL: br bb3
129115//
130116// CHECK-SIL: bb2:
@@ -151,34 +137,32 @@ final class Wallet {
151137 case empty
152138 case within( Wallet )
153139
154- init ( inWallet wallet: Wallet ? = nil ) {
155- self = . within( Wallet ( ) )
140+ consuming func changeTicket( inWallet wallet: Wallet ? = nil ) {
156141 if let existingWallet = wallet {
157142 _forget self
158143 self = . within( existingWallet)
159144 }
160145 }
161146 // As of now, we allow reinitialization after forget. Not sure if this is intended.
162- // CHECK-LABEL: sil hidden [ossa] @$s4test6TicketO8inWalletAcA0D0CSg_tcfC
147+ // CHECK-LABEL: sil hidden [ossa] @$s4test6TicketO06changeB08inWalletyAA0E0CSg_tF : $@convention(method) (@guaranteed Optional<Wallet>, @owned Ticket) -> () {
163148 // CHECK: [[SELF_REF:%.*]] = project_box [[SELF_BOX:%.*]] : ${ var Ticket }, 0
164- // CHECK: switch_enum {{.*}} : $Optional<Wallet>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
165- // CHECK: bb2({{%.*}} : @owned $Wallet):
166- // CHECK: br bb3
149+ // CHECK: switch_enum {{.*}} : $Optional<Wallet>, case #Optional.some!enumelt: [[HAVE_WALLET_BB:bb.*]], case #Optional.none!enumelt: {{.*}}
150+ //
167151 // >> now we begin the destruction sequence, which involves pattern matching on self to destroy its innards
168- // CHECK: bb3 :
152+ // CHECK: [[HAVE_WALLET_BB]]({{%.*}} : @owned $Wallet) :
169153 // CHECK: [[SELF_ACCESS:%.*]] = begin_access [read] [unknown] {{%.*}} : $*Ticket
170154 // CHECK: [[SELF_MMC:%.*]] = mark_must_check [no_consume_or_assign] [[SELF_ACCESS]]
171155 // CHECK: [[SELF_COPY:%.*]] = load [copy] [[SELF_MMC]] : $*Ticket
172156 // CHECK: end_access [[SELF_ACCESS:%.*]] : $*Ticket
173157 // CHECK: [[DD:%.*]] = drop_deinit [[SELF_COPY]] : $Ticket
174- // CHECK: switch_enum [[DD]] : $Ticket, case #Ticket.empty!enumelt: bb4 , case #Ticket.within!enumelt: bb5
175- // CHECK: bb4 :
176- // CHECK: br bb6
177- // CHECK: bb5 ([[PREV_SELF_WALLET:%.*]] : @owned $Wallet):
158+ // CHECK: switch_enum [[DD]] : $Ticket, case #Ticket.empty!enumelt: [[TICKET_EMPTY:bb[0-9]+]] , case #Ticket.within!enumelt: [[TICKET_WITHIN:bb[0-9]+]]
159+ // CHECK: [[TICKET_EMPTY]] :
160+ // CHECK: br [[JOIN_POINT:bb[0-9]+]]
161+ // CHECK: [[TICKET_WITHIN]] ([[PREV_SELF_WALLET:%.*]] : @owned $Wallet):
178162 // CHECK: destroy_value [[PREV_SELF_WALLET]] : $Wallet
179- // CHECK: br bb6
163+ // CHECK: br [[JOIN_POINT]]
180164 // >> from here on we are reinitializing self.
181- // CHECK: bb6 :
165+ // CHECK: [[JOIN_POINT]] :
182166 // CHECK: [[NEW_SELF_VAL:%.*]] = enum $Ticket, #Ticket.within!enumelt, {{.*}} : $Wallet
183167 // CHECK: [[SELF_ACCESS2:%.*]] = begin_access [modify] [unknown] [[SELF_REF]] : $*Ticket
184168 // CHECK: [[SELF_MMC2:%.*]] = mark_must_check [assignable_but_not_consumable] [[SELF_ACCESS2]] : $*Ticket
0 commit comments