@@ -546,7 +546,9 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
546
546
// We need to follow the partial_apply value for two reasons:
547
547
// 1. the closure (with the captured values) itself can escape
548
548
// 2. something can escape in a destructor when the context is destroyed
549
- return walkDownUses ( ofValue: pai, path: path. with ( knownType: nil ) )
549
+ if followLoads ( at: path) || pai. capturesAddress ( of: operand) {
550
+ return walkDownUses ( ofValue: pai, path: path. with ( knownType: nil ) )
551
+ }
550
552
case is LoadInst , is LoadWeakInst , is LoadUnownedInst , is LoadBorrowInst :
551
553
if !followLoads( at: path) {
552
554
return . continueWalk
@@ -966,3 +968,23 @@ private extension SmallProjectionPath {
966
968
EscapeUtilityTypes . EscapePath ( projectionPath: self , followStores: false , addressIsStored: false , knownType: nil )
967
969
}
968
970
}
971
+
972
+ private extension PartialApplyInst {
973
+ func capturesAddress( of operand: Operand ) -> Bool {
974
+ assert ( operand. value. type. isAddress)
975
+ guard let conv = convention ( of: operand) else {
976
+ fatalError ( " callee operand of partial_apply cannot have address type " )
977
+ }
978
+ switch conv {
979
+ case . indirectIn, . indirectInGuaranteed:
980
+ // A partial_apply copies the values from indirect-in arguments, but does not capture the address.
981
+ return false
982
+ case . indirectInout, . indirectInoutAliasable, . packInout:
983
+ return true
984
+ case . directOwned, . directUnowned, . directGuaranteed, . packOwned, . packGuaranteed:
985
+ fatalError ( " invalid convention for address operand " )
986
+ case . indirectOut, . packOut, . indirectInCXX:
987
+ fatalError ( " invalid convention for partial_apply " )
988
+ }
989
+ }
990
+ }
0 commit comments