@@ -180,12 +180,12 @@ class LocalVariableAccessInfo: CustomStringConvertible {
180180 case . beginAccess:
181181 switch ( localAccess. instruction as! BeginAccessInst ) . accessKind {
182182 case . read, . deinit:
183- _isFullyAssigned = . no
183+ self . _isFullyAssigned = . no
184184 case . `init`, . modify:
185185 break // lazily compute full assignment
186186 }
187187 case . load, . dependenceSource, . dependenceDest:
188- _isFullyAssigned = . no
188+ self . _isFullyAssigned = . no
189189 case . store, . storeBorrow:
190190 if let store = localAccess. instruction as? StoringInstruction {
191191 self . _isFullyAssigned = LocalVariableAccessInfo . isBase ( address: store. destination) ? . value : . no
@@ -196,20 +196,22 @@ class LocalVariableAccessInfo: CustomStringConvertible {
196196 case . apply:
197197 // This logic is consistent with AddressInitializationWalker.appliedAddressUse()
198198 let apply = localAccess. instruction as! FullApplySite
199- if let convention = apply. convention ( of: localAccess. operand!) {
200- if convention. isIndirectOut {
201- self . _isFullyAssigned = . value
202- }
203- if convention. isInout {
204- self . _isFullyAssigned = apply. fullyAssigns ( operand: localAccess. operand!)
205- }
199+ guard let convention = apply. convention ( of: localAccess. operand!) else {
200+ self . _isFullyAssigned = . no
201+ break
202+ }
203+ if convention. isIndirectOut {
204+ self . _isFullyAssigned = . value
205+ } else if convention. isInout {
206+ self . _isFullyAssigned = apply. fullyAssigns ( operand: localAccess. operand!)
207+ } else {
208+ self . _isFullyAssigned = . no
206209 }
207- _isFullyAssigned = . no
208210 case . escape:
209- _isFullyAssigned = . no
211+ self . _isFullyAssigned = . no
210212 self . hasEscaped = true
211213 case . inoutYield:
212- _isFullyAssigned = . no
214+ self . _isFullyAssigned = . no
213215 case . incomingArgument, . outgoingArgument, . deadEnd:
214216 fatalError ( " Function arguments are never mapped to LocalVariableAccessInfo " )
215217 }
@@ -222,7 +224,7 @@ class LocalVariableAccessInfo: CustomStringConvertible {
222224 var isEscape : Bool { access. isEscape }
223225
224226 /// Is this access a full assignment such that none of the variable's components are reachable from a previous
225- /// access.
227+ /// access? Only returns '.value' if this access does not read the incoming value .
226228 func isFullyAssigned( _ context: Context ) -> IsFullyAssigned {
227229 if let cached = _isFullyAssigned {
228230 return cached
@@ -232,7 +234,8 @@ class LocalVariableAccessInfo: CustomStringConvertible {
232234 }
233235 assert ( isModify)
234236 let beginAccess = access. instruction as! BeginAccessInst
235- if AddressInitializationWalker . findSingleInitializer ( ofAddress: beginAccess, requireFullyAssigned: . value, context)
237+ if AddressInitializationWalker . findSingleInitializer ( ofAddress: beginAccess, requireFullyAssigned: . value,
238+ allowRead: false , context)
236239 != nil {
237240 _isFullyAssigned = . value
238241 } else if AddressInitializationWalker . findSingleInitializer ( ofAddress: beginAccess,
@@ -956,7 +959,7 @@ extension LocalVariableReachableAccess {
956959 currentEffect = mode. getForwardEffect ( BlockEffect ( for: accessInfo, accessMap. context) ) . meet ( currentEffect)
957960 switch currentEffect! {
958961 case . assign:
959- if mode == . livenessUses {
962+ if mode == . livenessUses || accessInfo . isFullyAssigned ( context ) != . value {
960963 accessStack. push ( accessInfo. access)
961964 }
962965 return currentEffect
0 commit comments