@@ -72,12 +72,16 @@ let lifetimeDependenceDiagnosticsPass = FunctionPass(
72
72
markDep. settleToEscaping ( )
73
73
continue
74
74
}
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.
78
78
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) {
81
85
_ = analyze ( dependence: lifetimeDep, context)
82
86
}
83
87
}
@@ -237,10 +241,12 @@ private struct DiagnoseDependence {
237
241
onError ( )
238
242
239
243
// Identify the escaping variable.
240
- let escapingVar = LifetimeVariable ( dependent : operand. value , context)
244
+ let escapingVar = LifetimeVariable ( usedBy : operand, context)
241
245
if let varDecl = escapingVar. varDecl {
242
246
// 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 ?? " " )
244
250
} else if let sourceLoc = escapingVar. sourceLoc {
245
251
diagnose ( sourceLoc, . lifetime_value_outside_scope)
246
252
} else {
@@ -263,7 +269,7 @@ private struct DiagnoseDependence {
263
269
264
270
// Identify the dependence scope. If no source location is found, bypass this diagnostic.
265
271
func reportScope( ) {
266
- let parentVar = LifetimeVariable ( dependent : dependence. parentValue, context)
272
+ let parentVar = LifetimeVariable ( definedBy : dependence. parentValue, context)
267
273
// First check if the dependency is limited to an access scope. If the access has no source location then
268
274
// fall-through to report possible dependence on an argument.
269
275
if parentVar. isAccessScope, let accessLoc = parentVar. sourceLoc {
@@ -310,7 +316,22 @@ private struct LifetimeVariable {
310
316
return varDecl? . userFacingName
311
317
}
312
318
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 ) {
314
335
guard let introducer = getFirstVariableIntroducer ( of: value, context) else {
315
336
return
316
337
}
0 commit comments