Skip to content

Commit e409752

Browse files
committed
Lifetime diagnostics: clarify @_lifetime usage for inout parameters
This comes up often when passing a MutableSpan as an 'inout' argument. The vague diagnostic was causing developers to attempt incorrect @_lifetime annotations. Be clear about why the annotation is needed and which annotation should be used. (cherry picked from commit df0b81c)
1 parent 5265409 commit e409752

File tree

4 files changed

+28
-1
lines changed

4 files changed

+28
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8260,7 +8260,7 @@ ERROR(lifetime_dependence_feature_required_return, none,
82608260
ERROR(lifetime_dependence_feature_required_mutating, none,
82618261
"%0 cannot have a ~Escapable 'self'", (StringRef))
82628262
ERROR(lifetime_dependence_feature_required_inout, none,
8263-
"%0 cannot have a ~Escapable 'inout' parameter '%1'",
8263+
"%0 cannot have a ~Escapable 'inout' parameter '%1' in addition to other ~Escapable parameters",
82648264
// this arg list must be compatible with
82658265
// lifetime_dependence_cannot_infer_inout
82668266
(StringRef, StringRef))
@@ -8297,6 +8297,9 @@ ERROR(lifetime_dependence_cannot_infer_scope_ownership, none,
82978297
ERROR(lifetime_dependence_cannot_infer_implicit_init, none,
82988298
"cannot infer implicit initialization lifetime. Add an initializer with "
82998299
"'@_lifetime(...)' for each parameter the result depends on", ())
8300+
NOTE(lifetime_dependence_cannot_infer_inout_suggest, none,
8301+
"use '@_lifetime(%0: copy %0) to forward the inout dependency",
8302+
(StringRef))
83008303

83018304
//------------------------------------------------------------------------------
83028305
// MARK: Lifetime Dependence Experimental Inference

lib/AST/LifetimeDependence.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,12 @@ class LifetimeDependenceChecker {
555555
ctx.Diags.diagnose(param->getLoc(), diagID,
556556
{StringRef(diagnosticQualifier()),
557557
param->getName().str()});
558+
if (diagID == diag::lifetime_dependence_cannot_infer_inout.ID) {
559+
ctx.Diags.diagnose(
560+
param->getLoc(),
561+
diag::lifetime_dependence_cannot_infer_inout_suggest,
562+
param->getName().str());
563+
}
558564
}
559565
}
560566
}

test/Sema/lifetime_attr_nofeature.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ struct NE : ~Escapable { // expected-error{{an implicit initializer cannot retur
88
func derive(_ ne: NE) -> NE { // expected-error{{a function cannot return a ~Escapable result}}
99
ne
1010
}
11+
12+
func f_inout_infer(a: inout MutableRawSpan) {}
13+
14+
func f_inout_no_infer(a: inout MutableRawSpan, b: RawSpan) {}
15+
// expected-error @-1{{a function cannot have a ~Escapable 'inout' parameter 'a' in addition to other ~Escapable parameters}}
16+

test/Sema/lifetime_depend_infer.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ struct NEImmortal: ~Escapable {
1515
init() {}
1616
}
1717

18+
struct MutNE: ~Copyable & ~Escapable {}
19+
1820
// =============================================================================
1921
// Handle non-Escapable results with 'self'
2022
// =============================================================================
@@ -613,3 +615,13 @@ struct NE_NE_C: ~Escapable { // expected-error{{cannot infer implicit initializa
613615
let ne: NE
614616
let c: C
615617
}
618+
619+
// =============================================================================
620+
// Handle common mistakes with inout parameter annotations
621+
// =============================================================================
622+
623+
// Unable to infer an 'inout' dependency. Provide valid guidance.
624+
//
625+
func f_inout_no_infer(a: inout MutNE, b: NE) {} // expected-error{{a function with a ~Escapable 'inout' parameter requires '@_lifetime(a: ...)'}}
626+
// expected-note @-1{{use '@_lifetime(a: copy a) to forward the inout dependency}}
627+

0 commit comments

Comments
 (0)