@@ -128,27 +128,36 @@ private func analyze(dependence: LifetimeDependence, _ context: FunctionPassCont
128128 var range = dependence. computeRange ( context)
129129 defer { range? . deinitialize ( ) }
130130
131- var error = false
132- let diagnostics =
133- DiagnoseDependence ( dependence: dependence, range: range,
134- onError: { error = true } , context: context)
131+ let diagnostics = DiagnoseDependence ( dependence: dependence, range: range, context: context)
135132
136133 // Check each lifetime-dependent use via a def-use visitor
137134 var walker = DiagnoseDependenceWalker ( diagnostics, context)
138135 defer { walker. deinitialize ( ) }
139136 let result = walker. walkDown ( dependence: dependence)
140- // The walk may abort without a diagnostic error.
141- assert ( !error || result == . abortWalk )
137+ assert ( result == . continueWalk || diagnostics . errorStatus != nil ,
138+ " Lifetime diagnostics failed without raising an error " )
142139 return result == . continueWalk
143140}
144141
145142/// Analyze and diagnose a single LifetimeDependence.
146- private struct DiagnoseDependence {
143+ private class DiagnoseDependence {
144+ enum ErrorStatus {
145+ case diagnostic
146+ case unresolvedDependence
147+ }
148+
147149 let dependence : LifetimeDependence
148150 let range : InstructionRange ?
149- let onError : ( ) -> ( )
150151 let context : FunctionPassContext
151152
153+ init ( dependence: LifetimeDependence , range: InstructionRange ? , context: FunctionPassContext ) {
154+ self . dependence = dependence
155+ self . range = range
156+ self . context = context
157+ }
158+
159+ var errorStatus : ErrorStatus ? = nil
160+
152161 var function : Function { dependence. function }
153162
154163 func diagnose( _ position: SourceLoc ? , _ id: DiagID ,
@@ -266,9 +275,10 @@ private struct DiagnoseDependence {
266275 func reportError( escapingValue: Value , user: Instruction , diagID: DiagID ) {
267276 // If the dependent value is Escapable, then mark_dependence resolution fails, but this is not a diagnostic error.
268277 if dependence. dependentValue. isEscapable {
278+ errorStatus = . unresolvedDependence
269279 return
270280 }
271- onError ( )
281+ errorStatus = . diagnostic
272282
273283 // Identify the escaping variable.
274284 let escapingVar = LifetimeVariable ( definedBy: escapingValue, user: user, context)
@@ -598,10 +608,10 @@ extension DiagnoseDependenceWalker : LifetimeDependenceDefUseWalker {
598608 return . continueWalk
599609 }
600610
601- // Override AddressUseVisitor here because LifetimeDependenceDefUseWalker
602- // returns .abortWalk, and we want a more useful crash report .
611+ // Override AddressUseVisitor here because LifetimeDependenceDefUseWalker returns .abortWalk and
612+ // DiagnoseDependenceWalker requires a diagnostic error for all aborts .
603613 mutating func unknownAddressUse( of operand: Operand ) -> WalkResult {
604614 diagnostics. reportUnknown ( operand: operand)
605- return . continueWalk
615+ return . abortWalk
606616 }
607617}
0 commit comments