@@ -72,12 +72,16 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
7272 markDep. settleToEscaping ( )
7373 continue
7474 }
75- if let apply = instruction as? FullApplySite {
76- // Handle ~Escapable results that do not have a lifetime dependence. This includes implicit initializers and
77- // @_unsafeNonescapableResult.
75+ if let apply = instruction as? FullApplySite , !apply . hasResultDependence {
76+ // Handle ~Escapable results that do not have a lifetime dependence. This includes implicit initializers, calls to
77+ // closures, and @_unsafeNonescapableResult.
7878 apply. resultOrYields. forEach {
79- if let lifetimeDep = LifetimeDependence ( unsafeApplyResult: $0,
80- context) {
79+ if let lifetimeDep = LifetimeDependence ( unsafeApplyResult: $0, apply: apply, context) {
80+ _ = analyze ( dependence: lifetimeDep, context)
81+ }
82+ }
83+ apply. indirectResultOperands. forEach {
84+ if let lifetimeDep = LifetimeDependence ( unsafeApplyResult: $0. value, apply: apply, context) {
8185 _ = analyze ( dependence: lifetimeDep, context)
8286 }
8387 }
@@ -237,10 +241,12 @@ private struct DiagnoseDependence {
237241 onError ( )
238242
239243 // Identify the escaping variable.
240- let escapingVar = LifetimeVariable ( dependent : operand. value , context)
244+ let escapingVar = LifetimeVariable ( usedBy : operand, context)
241245 if let varDecl = escapingVar. varDecl {
242246 // Use the variable location, not the access location.
243- diagnose ( varDecl. nameLoc, . lifetime_variable_outside_scope, escapingVar. name ?? " " )
247+ // Variable names like $return_value and $implicit_value don't have source locations.
248+ let sourceLoc = varDecl. nameLoc ?? escapingVar. sourceLoc
249+ diagnose ( sourceLoc, . lifetime_variable_outside_scope, escapingVar. name ?? " " )
244250 } else if let sourceLoc = escapingVar. sourceLoc {
245251 diagnose ( sourceLoc, . lifetime_value_outside_scope)
246252 } else {
@@ -263,7 +269,7 @@ private struct DiagnoseDependence {
263269
264270 // Identify the dependence scope. If no source location is found, bypass this diagnostic.
265271 func reportScope( ) {
266- let parentVar = LifetimeVariable ( dependent : dependence. parentValue, context)
272+ let parentVar = LifetimeVariable ( definedBy : dependence. parentValue, context)
267273 // First check if the dependency is limited to an access scope. If the access has no source location then
268274 // fall-through to report possible dependence on an argument.
269275 if parentVar. isAccessScope, let accessLoc = parentVar. sourceLoc {
@@ -310,7 +316,22 @@ private struct LifetimeVariable {
310316 return varDecl? . userFacingName
311317 }
312318
313- init ( dependent value: Value , _ context: some Context ) {
319+ init ( usedBy operand: Operand , _ context: some Context ) {
320+ self = . init( dependent: operand. value, context)
321+ // variable names like $return_value and $implicit_value don't have source locations.
322+ // For @out arguments, the operand's location is the best answer.
323+ // Otherwise, fall back to the function's location.
324+ self . sourceLoc = self . sourceLoc ?? operand. instruction. location. sourceLoc
325+ ?? operand. instruction. parentFunction. location. sourceLoc
326+ }
327+
328+ init ( definedBy value: Value , _ context: some Context ) {
329+ self = . init( dependent: value, context)
330+ // Fall back to the function's location.
331+ self . sourceLoc = self . sourceLoc ?? value. parentFunction. location. sourceLoc
332+ }
333+
334+ private init ( dependent value: Value , _ context: some Context ) {
314335 guard let introducer = getFirstVariableIntroducer ( of: value, context) else {
315336 return
316337 }
0 commit comments