I've run into a really annoying problem involving non-Escapable types that have inout access to their source. If I create one of these on a struct member, it makes the entire struct inaccessible, not just the field that's being accessed.
Here's a simplified example:
import Foundation
struct Foo {
var data = Data(repeating: 0, count: 100)
var n = 0
mutating func modify() -> Int {
let span = data.mutableSpan //ERROR: Overlapping accesses to 'self', but modification requires exclusive access
n += span.count
return n
}
}
It took me a while to figure out the problem. In the modify method, the variable span has inout access to data, so data can't be accessed while it exists. That's a good thing.
But because data is embedded inside self, the compiler considers self to be inout-accessed, so other fields like n can't be accessed either!
The advice is to "consider making a copy", but in my real code it's not a Span it's a non-copyable type, so that's out. I could move that value to a temporary, but that has the side effect of consuming self, which is even worse!
In my real code the struct member is a type of database cursor and the non-escapable value I get from it is a row, so it's like
func nextRow() {
guard let row = try _stmt.next() else {return nil}
...
}
Basically as long as row exists, _stmt is off-limits (which is great, because moving the cursor invalidates the values row points to) but I can't access self either! The only workaround seems to be to copy everything I need out of row, then use that to operate on self.