@@ -204,6 +204,50 @@ enum BorrowingInstruction : CustomStringConvertible, Hashable {
204
204
}
205
205
}
206
206
207
+ var dependentValue : Value ? {
208
+ switch self {
209
+ case . borrowedFrom( let bfi) :
210
+ let phi = bfi. borrowedPhi
211
+ if phi. isReborrow {
212
+ return nil
213
+ }
214
+ return phi. value
215
+ case . markDependence( let mdi) :
216
+ if mdi. hasScopedLifetime {
217
+ return nil
218
+ }
219
+ return mdi
220
+ case . beginBorrow, . storeBorrow, . beginApply, . partialApply, . startAsyncLet:
221
+ return nil
222
+ }
223
+ }
224
+
225
+ /// If this is valid, then visitScopeEndingOperands succeeds.
226
+ var scopedValue : Value ? {
227
+ switch self {
228
+ case . beginBorrow, . storeBorrow:
229
+ return instruction as! SingleValueInstruction
230
+ case let . borrowedFrom( bfi) :
231
+ let phi = bfi. borrowedPhi
232
+ guard phi. isReborrow else {
233
+ return nil
234
+ }
235
+ return phi. value
236
+ case . beginApply( let bai) :
237
+ return bai. token
238
+ case . partialApply( let pai) :
239
+ // We currently assume that closure lifetimes are always complete (destroyed on all paths).
240
+ return pai
241
+ case . markDependence( let mdi) :
242
+ guard mdi. hasScopedLifetime else {
243
+ return nil
244
+ }
245
+ return mdi
246
+ case . startAsyncLet( let builtin) :
247
+ return builtin
248
+ }
249
+ }
250
+
207
251
/// Visit the operands that end the local borrow scope.
208
252
///
209
253
/// Returns .abortWalk if the borrow scope cannot be determined from lifetime-ending uses. For example:
@@ -218,26 +262,23 @@ enum BorrowingInstruction : CustomStringConvertible, Hashable {
218
262
/// TODO: For instructions that are not a BeginBorrowValue, verify that scope ending instructions exist on all
219
263
/// paths. These instructions should be complete after SILGen and never cloned to produce phis.
220
264
func visitScopeEndingOperands( _ context: Context , visitor: @escaping ( Operand ) -> WalkResult ) -> WalkResult {
265
+ guard let val = scopedValue else {
266
+ return . abortWalk
267
+ }
221
268
switch self {
222
269
case . beginBorrow, . storeBorrow:
223
- return visitEndBorrows ( value: instruction as! SingleValueInstruction , context, visitor)
224
- case let . borrowedFrom( bfi) :
225
- guard bfi. borrowedPhi. isReborrow else {
226
- return . abortWalk
227
- }
228
- return visitEndBorrows ( value: instruction as! SingleValueInstruction , context, visitor)
229
- case . beginApply( let bai) :
230
- return bai. token. uses. walk { return visitor ( $0) }
231
- case . partialApply( let pai) :
270
+ return visitEndBorrows ( value: val, context, visitor)
271
+ case . borrowedFrom:
272
+ return visitEndBorrows ( value: val, context, visitor)
273
+ case . beginApply:
274
+ return val. uses. walk { return visitor ( $0) }
275
+ case . partialApply:
232
276
// We currently assume that closure lifetimes are always complete (destroyed on all paths).
233
- return visitOwnedDependent ( value: pai, context, visitor)
234
- case . markDependence( let mdi) :
235
- guard mdi. ownership == . owned, mdi. type. isEscapable ( in: mdi. parentFunction) else {
236
- return . abortWalk
237
- }
238
- return visitOwnedDependent ( value: mdi, context, visitor)
239
- case . startAsyncLet( let builtin) :
240
- return builtin. uses. walk {
277
+ return visitOwnedDependent ( value: val, context, visitor)
278
+ case . markDependence:
279
+ return visitOwnedDependent ( value: val, context, visitor)
280
+ case . startAsyncLet:
281
+ return val. uses. walk {
241
282
if let builtinUser = $0. instruction as? BuiltinInst ,
242
283
builtinUser. id == . EndAsyncLetLifetime {
243
284
return visitor ( $0)
0 commit comments