Files
swift-mirror/test/Sema/lifetime_depend_infer.swift
Andrew Trick 7abe2222f9 Disable surprising lifetime inference of implicit initializers
Non-escapable struct definitions often have inicidental integer fields that are
unrelated to lifetime. Without an explicit initializer, the compiler would infer
these fields to be borrowed by the implicit intializer.

    struct CountedSpan: ~Escapable {
      let span: Span<Int>
      let i: Int

      /* infer: @lifetime(copy span, borrow i) init(...) */
    }

This was done because
- we always want to infer lifetimes of synthesized code if possible
- inferring a borrow dependence is always conservative

But this was the wrong decision because it inevitabely results in lifetime
diagnostic errors elsewhere in the code that can't be tracked down at the use
site:

    let span = CountedSpan(span: span, i: 3) // ERROR: span depends on the lifetime of this value

Instead, force the author of the data type to specify whether the type actually
depends on trivial fields or not. Such as:

    struct CountedSpan: ~Escapable {
      let span: Span<Int>
      let i: Int

      @lifetime(copy span) init(...) { ... }
    }

This fix enables stricter diagnostics, so we need it in 6.2.

Fixes rdar://152130977 ([nonescapable] confusing diagnostic message when a
synthesized initializer generates dependence on an Int parameter)
2025-06-26 12:47:01 -07:00

652 lines
25 KiB
Swift

// RUN: %target-typecheck-verify-swift \
// RUN: -enable-experimental-feature Lifetimes
// REQUIRES: swift_feature_Lifetimes
// Coverage testing for LifetimeDependence inferrence logic. The tests are grouped according to the design of
// LifetimeDependenceChecker.
class C {}
struct NE: ~Escapable {}
struct NEImmortal: ~Escapable {
@_lifetime(immortal)
init() {}
}
struct MutNE: ~Copyable & ~Escapable {}
// =============================================================================
// Handle non-Escapable results with 'self'
// =============================================================================
struct NonEscapableSelf: ~Escapable {
func methodNoParam() -> NonEscapableSelf { self } // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
func methodNoParamLifetime() -> NonEscapableSelf { self }
@_lifetime(copy self) // OK
func methodNoParamCopy() -> NonEscapableSelf { self }
@_lifetime(borrow self) // OK
func methodNoParamBorrow() -> NonEscapableSelf { self }
mutating func mutatingMethodNoParam() -> NonEscapableSelf { self } // expected-error{{a mutating method with a ~Escapable result requires '@_lifetime(...)'}}
// expected-error@-1{{a mutating method with a ~Escapable 'self' requires '@_lifetime(self: ...)'}}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
mutating func mutatingMethodNoParamLifetime() -> NonEscapableSelf { self }
@_lifetime(copy self) // OK
mutating func mutatingMethodNoParamCopy() -> NonEscapableSelf { self }
@_lifetime(&self) // OK
mutating func mutatingMethodNoParamBorrow() -> NonEscapableSelf { self }
func methodOneParam(_: Int) -> NonEscapableSelf { self } // expected-error{{a method with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
func methodOneParamLifetime(_: Int) -> NonEscapableSelf { self }
@_lifetime(copy self) // OK
func methodOneParamCopy(_: Int) -> NonEscapableSelf { self }
@_lifetime(borrow self) // OK
func methodOneParamBorrow(_: Int) -> NonEscapableSelf { self }
mutating func mutatingMethodOneParam(_: Int) -> NonEscapableSelf { self } // expected-error{{a mutating method with a ~Escapable result requires '@_lifetime(...)'}}
// expected-error@-1{{a mutating method with a ~Escapable 'self' requires '@_lifetime(self: ...)'}}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
mutating func mutatingMethodOneParamLifetime(_: Int) -> NonEscapableSelf { self }
@_lifetime(copy self) // OK
mutating func mutatingMethodOneParamCopy(_: Int) -> NonEscapableSelf { self }
@_lifetime(&self) // OK
mutating func mutatingMethodOneParamBorrow(_: Int) -> NonEscapableSelf { self }
}
struct EscapableTrivialSelf {
func methodNoParam() -> NEImmortal { NEImmortal() } // expected-error{{cannot infer lifetime dependence on a method because 'self' is BitwiseCopyable}}
@_lifetime(self) // OK
func methodNoParamLifetime() -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(borrow self)' instead}}
func methodNoParamCopy() -> NEImmortal { NEImmortal() }
@_lifetime(borrow self) // OK
func methodNoParamBorrow() -> NEImmortal { NEImmortal() }
func mutatingMethodNoParam() -> NEImmortal { NEImmortal() } // expected-error{{cannot infer lifetime dependence on a method because 'self' is BitwiseCopyable}}
@_lifetime(self) // OK
mutating func mutatingMethodNoParamLifetime() -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(&self)' instead}}
mutating func mutatingMethodNoParamCopy() -> NEImmortal { NEImmortal() }
@_lifetime(&self)
mutating func mutatingMethodNoParamBorrow() -> NEImmortal { NEImmortal() }
func methodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a method with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(self)
func methodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(borrow self)' instead}}
func methodOneParamCopy(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(borrow self)
func methodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
mutating func mutatingMethodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a mutating method with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(self)
mutating func mutatingMethodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(&self)' instead}}
mutating func mutatingMethodOneParamCopy(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(&self)
mutating func mutatingMethodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
}
struct EscapableNonTrivialSelf {
let c: C
init(c: C) { self.c = c }
func methodNoParam() -> NEImmortal { NEImmortal() }
@_lifetime(self)
func methodNoParamLifetime() -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(borrow self)' instead}}
func methodNoParamCopy() -> NEImmortal { NEImmortal() }
@_lifetime(borrow self)
func methodNoParamBorrow() -> NEImmortal { NEImmortal() }
mutating func mutatingMethodNoParam() -> NEImmortal { NEImmortal() }
func methodInoutNonEscapableParam(_: inout NE) {}
mutating func mutatingMethodInoutNonEscapableParam(_: inout NE) {}
@_lifetime(self)
mutating func mutatingMethodNoParamLifetime() -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(&self)' instead}}
mutating func mutatingMethodNoParamCopy() -> NEImmortal { NEImmortal() }
@_lifetime(&self)
mutating func mutatingMethodNoParamBorrow() -> NEImmortal { NEImmortal() }
func methodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a method with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(self)
func methodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(borrow self)' instead}}
func methodOneParamCopy(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(borrow self)
func methodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
mutating func mutatingMethodOneParam(_: Int) -> NEImmortal { NEImmortal() } // expected-error{{a mutating method with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(self)
mutating func mutatingMethodOneParamLifetime(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(copy self) // expected-error{{cannot copy the lifetime of an Escapable type, use '@_lifetime(&self)' instead}}
mutating func mutatingMethodOneParamCopy(_: Int) -> NEImmortal { NEImmortal() }
@_lifetime(&self)
mutating func mutatingMethodOneParamBorrow(_: Int) -> NEImmortal { NEImmortal() }
}
// =============================================================================
// Handle non-Escapable results which must depend on a parameter
// (for initializers and stand-alone functions)
// =============================================================================
// An implicit initializer illegally consumes its nontrivial parameter.
public struct NonescapableImplicitInitializer: ~Escapable {
// expected-error @-1{{cannot borrow the lifetime of 'c', which has consuming ownership on an implicit initializer}}
var c: C
}
struct NonescapableInitializers: ~Escapable {
var c: C
init() { c = C() } // expected-error{{an initializer with a ~Escapable result needs a parameter to depend on}}
// expected-note@-1{{'@_lifetime(immortal)' can be used to indicate that values produced by this initializer have no lifetime dependencies}}
init(c: C) { self.c = c } // expected-error{{cannot borrow the lifetime of 'c', which has consuming ownership on an initializer}}
init(c: C, _: Int) { self.c = c } // expected-error{{an initializer with a ~Escapable result requires '@_lifetime(...)'}}
init(ne: NE) { c = C() } // expected-error{{cannot infer the lifetime dependence scope on an initializer with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
}
struct NonescapableConsumingInitializers: ~Escapable {
var c: C // implicit get/set is OK
init(c: consuming C) { self.c = c } // expected-error{{cannot borrow the lifetime of 'c', which has consuming ownership on an initializer}}
init(c: consuming C, _: Int) { self.c = c } // expected-error{{an initializer with a ~Escapable result requires '@_lifetime(...)'}}
init(ne: consuming NE) { c = C() } // expected-error{{cannot infer the lifetime dependence scope on an initializer with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
}
struct NonescapableBorrowingInitializers: ~Escapable {
var c: C // implicit stored property set is OK
init(c: borrowing C) { self.c = c } // OK
init(c: borrowing C, _: Int) { self.c = c } // expected-error{{an initializer with a ~Escapable result requires '@_lifetime(...)'}}
init(ne: borrowing NE) { c = C() } // expected-error{{cannot infer the lifetime dependence scope on an initializer with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
}
struct NonescapableInoutInitializers: ~Escapable {
var c: C // implicit stored property set is OK
init(c: inout C) { self.c = c } // OK
init(c: inout C, _: Int) { self.c = c } // expected-error{{an initializer with a ~Escapable result requires '@_lifetime(...)'}}
init(ne: inout NE) { c = C() } // expected-error{{cannot infer the lifetime dependence scope on an initializer with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
}
func noParam() -> NEImmortal { NEImmortal() } // expected-error{{a function with a ~Escapable result needs a parameter to depend on}}
// expected-note@-1{{'@_lifetime(immortal)' can be used to indicate that values produced by this initializer have no lifetime dependencies}}
@_lifetime(immortal)
func noParamImmortal() -> NEImmortal { NEImmortal() } // OK
func oneParam(c: C) -> NEImmortal { NEImmortal() }
@_lifetime(c)
func oneParamLifetime(c: C) -> NEImmortal { NEImmortal() }
func oneParamConsume(c: consuming C) -> NEImmortal { NEImmortal() } // expected-error{{cannot borrow the lifetime of 'c', which has consuming ownership on a function}}
@_lifetime(c) // expected-error{{invalid lifetime dependence on an Escapable value with consuming ownership}}
func oneParamConsumeLifetime(c: consuming C) -> NEImmortal { NEImmortal() }
func oneParamBorrow(c: borrowing C) -> NEImmortal { NEImmortal() } // OK
@_lifetime(c)
func oneParamBorrowLifetime(c: borrowing C) -> NEImmortal { NEImmortal() } // OK
func oneParamInout(c: inout C) -> NEImmortal { NEImmortal() } // OK
@_lifetime(c)
func oneParamInoutLifetime(c: inout C) -> NEImmortal { NEImmortal() } // OK
func twoParams(c: C, _: Int) -> NEImmortal { NEImmortal() } // expected-error{{a function with a ~Escapable result requires '@_lifetime(...)'}}
@_lifetime(c)
func twoParamsLifetime(c: C, _: Int) -> NEImmortal { NEImmortal() }
func twoParamsConsume(c: consuming C, _: Int) -> NEImmortal { NEImmortal() } // expected-error{{a function with a ~Escapable result requires '@_lifetime(...)'}}
func twoParamsBorrow(c: borrowing C, _: Int) -> NEImmortal { NEImmortal() } // expected-error{{a function with a ~Escapable result requires '@_lifetime(...)'}}
func twoParamsInout(c: inout C, _: Int) -> NEImmortal { NEImmortal() } // expected-error{{a function with a ~Escapable result requires '@_lifetime(...)'}}
func neParam(ne: NE) -> NE { ne } // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
@_lifetime(ne) // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
func neParamLifetime(ne: NE) -> NE { ne }
func neParamBorrow(ne: borrowing NE) -> NE { ne } // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
@_lifetime(ne) // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
func neParamBorrowLifetime(ne: borrowing NE) -> NE { ne }
func neParamConsume(ne: consuming NE) -> NE { ne } // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
@_lifetime(ne) // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
func neParamConsumeLifetime(ne: consuming NE) -> NE { ne }
func neParamInout(ne: inout NE) -> NE { ne } // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
@_lifetime(ne) // expected-error{{cannot infer the lifetime dependence scope on a function with a ~Escapable parameter, specify '@_lifetime(borrow ne)' or '@_lifetime(copy ne)'}}
func neParamInoutLifetime(ne: inout NE) -> NE { ne }
func neTwoParam(ne: NE, _:Int) -> NE { ne } // expected-error{{a function with a ~Escapable result requires '@_lifetime(...)'}}
func voidInoutOneParam(_: inout NE) {} // OK
func voidInoutTwoParams(_: inout NE, _: Int) {} // OK
// =============================================================================
// Handle Accessors:
//
// 'get', '_read', and '_modify' are inferred as methods that return ~Escpable results dependent on 'self'
//
// 'set' is only inferred when implicit. This allows for the declaration of non-Escapable stored properties. Knowing
// that the implicit setter assigns a stored property is sufficient for the compiler to assume Inherit dependency on
// both 'self' and 'newValue'. A full assignment would not need the 'self' dependency.
// =============================================================================
struct Accessors {
let c: C
var neComputed: NEImmortal {
get { // OK
NEImmortal()
}
set { // OK (no dependency)
}
}
var neYielded: NEImmortal {
_read { // OK
yield NEImmortal()
}
_modify { // OK
var ne = NEImmortal()
yield &ne
}
}
}
struct TrivialAccessors {
let p: UnsafeRawPointer
// The implicit _read/_modify accessors must be inferred. They cannot be written explicitly because a getter is
// already defined.
var neComputed: NEImmortal {
@_lifetime(borrow self)
get { // OK
NEImmortal()
}
@_lifetime(&self)
set { // OK (no dependency)
}
}
var neYielded: NEImmortal {
@_lifetime(borrow self)
_read { // OK
yield NEImmortal()
}
@_lifetime(&self)
_modify { // OK
var ne = NEImmortal()
yield &ne
}
}
}
struct NonescapableSelfAccessors: ~Escapable {
var ne: NE
@_lifetime(immortal)
init() {
ne = NE()
}
var neComputed: NE {
get { // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
ne
}
set { // expected-error{{a mutating method with a ~Escapable 'self' requires '@_lifetime(self: ...)'}}
ne = newValue
}
}
var neYielded: NE {
_read { // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
yield ne
}
@_lifetime(&self)
_modify {
yield &ne
}
}
var neComputedLifetime: NE {
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
get {
ne
}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
set {
ne = newValue
}
}
var neYieldedLifetime: NE {
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
_read {
yield ne
}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
_modify {
yield &ne
}
}
var neComputedCopy: NE {
@_lifetime(copy self)
get {
ne
}
@_lifetime(copy self)
set {
ne = newValue
}
}
var neYieldedCopy: NE {
@_lifetime(copy self)
_read {
yield ne
}
@_lifetime(copy self)
_modify {
yield &ne
}
}
var neComputedBorrow: NE {
@_lifetime(borrow self)
get {
ne
}
@_lifetime(&self)
set {
ne = newValue
}
}
var neYieldedBorrow: NE {
@_lifetime(borrow self)
_read {
yield ne
}
@_lifetime(&self)
_modify {
yield &ne
}
}
}
struct NoncopyableSelfAccessors: ~Copyable & ~Escapable {
var ne: NE
var neComputed: NE {
get { // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
ne
}
set { // expected-error{{a mutating method with a ~Escapable 'self' requires '@_lifetime(self: ...)'}}
ne = newValue
}
}
var neYielded: NE {
_read { // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
yield ne
}
@_lifetime(&self)
_modify {
yield &ne
}
}
var neComputedLifetime: NE {
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
get {
ne
}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
set {
ne = newValue
}
}
var neYieldedLifetime: NE {
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
_read {
yield ne
}
@_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
_modify {
yield &ne
}
}
var neComputedCopy: NE {
@_lifetime(copy self)
get {
ne
}
@_lifetime(copy self)
set {
ne = newValue
}
}
var neYieldedCopy: NE {
@_lifetime(copy self)
_read {
yield ne
}
@_lifetime(copy self)
_modify {
yield &ne
}
}
var neComputedBorrow: NE {
@_lifetime(borrow self)
get {
ne
}
@_lifetime(&self)
set {
ne = newValue
}
}
var neYieldedBorrow: NE {
@_lifetime(borrow self)
_read {
yield ne
}
@_lifetime(&self)
_modify {
yield &ne
}
}
}
// =============================================================================
// Handle mutating methods with no return value
// =============================================================================
struct NonEscapableMutableSelf: ~Escapable {
// This is unambiguous: inout 'self' needs a dependency, and it can't be a borrow dependency because the original
// value is consumed.
/* @_lifetime(self: copy self) */
mutating func mutatingMethodNoParam() {} // OK
@_lifetime(self: self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
mutating func mutatingMethodNoParamLifetime() {}
@_lifetime(self: copy self) // OK
mutating func mutatingMethodNoParamCopy() {}
@_lifetime(self: &self) // expected-error{{invalid use of inout dependence on the same inout parameter}}
// expected-note @-1{{use '@_lifetime(self: copy self) to forward the inout dependency}}
mutating func mutatingMethodNoParamBorrow() {}
mutating func mutatingMethodOneParam(_: NE) {} // expected-error{{a mutating method with a ~Escapable 'self' requires '@_lifetime(self: ...)'}}
@_lifetime(self: self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}}
mutating func mutatingMethodOneParamLifetime(_: NE) {}
@_lifetime(copy self) // OK
mutating func mutatingMethodOneParamCopy(_: NE) {}
@_lifetime(&self)
mutating func mutatingMethodOneParamBorrow(_: NE) {}
}
// =============================================================================
// Initializers
// =============================================================================
// Motivation: Non-escapable struct definitions often have inicidental integer fields that are unrelated to lifetime.
// Without an explicit initializer, the compiler would infer these fields to be borrowed by the implicit intializer.
// This inevitabely results in lifetime diagnostic errors elsewhere in the code that can't be tracked down at the use
// site:
//
// let span = CountedSpan(span: span, i: 3) // ERROR: span depends on the lifetime of this value
//
struct CountedSpan: ~Escapable { // expected-error{{cannot infer implicit initialization lifetime. Add an initializer with '@_lifetime(...)' for each parameter the result depends on}}
let span: Span<Int>
let i: Int
}
struct NE_Int: ~Escapable {
let i: Int
}
struct NE_C: ~Escapable { // expected-error{{cannot borrow the lifetime of 'c', which has consuming ownership on an implicit initializer}}
let c: C
}
struct NE_C_Int: ~Escapable { // expected-error{{cannot infer implicit initialization lifetime. Add an initializer with '@_lifetime(...)' for each parameter the result depends on}}
let c: C
let i: Int
}
struct NE_Int_Int: ~Escapable { // expected-error{{cannot infer implicit initialization lifetime. Add an initializer with '@_lifetime(...)' for each parameter the result depends on}}
let i: Int
let j: Int
}
struct NE_NE: ~Escapable {
let ne: NE
}
struct NE_NE_Int: ~Escapable { // expected-error{{cannot infer implicit initialization lifetime. Add an initializer with '@_lifetime(...)' for each parameter the result depends on}}
let ne: NE
let i: Int
}
struct NE_NE_C: ~Escapable { // expected-error{{cannot infer implicit initialization lifetime. Add an initializer with '@_lifetime(...)' for each parameter the result depends on}}
let ne: NE
let c: C
}
// =============================================================================
// Handle common mistakes with inout parameter annotations
// =============================================================================
// Unable to infer an 'inout' dependency. Provide valid guidance.
//
func f_inout_no_infer(a: inout MutNE, b: NE) {}
// expected-error @-1{{a function with a ~Escapable 'inout' parameter requires '@_lifetime(a: ...)'}}
// expected-note @-2{{use '@_lifetime(a: copy a) to forward the inout dependency}}
// Invalid keyword for the dependence kind.
//
@_lifetime(a: inout a) // expected-error{{expected 'copy', 'borrow', or '&' followed by an identifier, index or 'self' in lifetime dependence specifier}}
func f_inout_bad_keyword(a: inout MutableRawSpan) {}
// Don't allow a useless borrow dependency on an inout param--it is misleading.
//
@_lifetime(a: &a) // expected-error{{invalid use of inout dependence on the same inout parameter}}
// expected-note @-1{{use '@_lifetime(a: copy a) to forward the inout dependency}}
func f_inout_useless(a: inout MutableRawSpan) {}