The following codes compile successfully:
struct B: ~Escapable {
@_lifetime(immortal)
init() {}
func doSomething() {}
}
struct A: ~Copyable {
var b: B {
@_lifetime(borrow self)
get {
return .init()
}
}
consuming func consume() {}
}
func test() {
var a = A()
do {
let b = a.b
b.doSomething()
}
a.consume()
}
However, if we change the var a = A() to let a = A():
struct B: ~Escapable {
@_lifetime(immortal)
init() {}
func doSomething() {}
}
struct A: ~Copyable {
var b: B {
@_lifetime(borrow self)
get {
return .init()
}
}
consuming func consume() {}
}
func test() {
let a = A() // <-- change from var to let
do {
let b = a.b
b.doSomething()
}
a.consume()
// error: Noncopyable 'a' cannot be consumed when captured by an escaping closure or borrowed by a non-Escapable type
}
We got an error on a.consume() saying we cannot consume a because it is still being borrowed by a non-Escapable type. But here the lifetime of b has already been ended after the do block and should not affect a anymore. Besides, it only occurs when a is a let constant. This issue persists in 6.2, 6.3 and 6.4 beta. Is there any workaround for that? Using var instead of let pass the compilation, but will also give a warning saying a was never mutated.