-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
Consider the following setup:
struct Collector: ~Copyable {
private var collected: String = ""
mutating func collect(data newData: String) {
self.collected += newData
}
}
struct LoggingCollector: ~Copyable, ~Escapable {
var underlying: UnsafeMutablePointer<Collector>
init(underlying: UnsafeMutablePointer<Collector>) {
self.underlying = underlying
}
@_lifetime(&self)
mutating func collect(data newData: String) {
print(newData)
underlying.pointee.collect(data: newData)
}
}The idea is that LoggingCollector effectively holds an inout reference to Collector and acts as a wrapper around it that also performs some work on its own. For that, we need to ensure that the underlying Collector always outlives the LoggingCollector. Currently, that responsibility is on the caller due to UnsafeMutablePointer. It would be nice if we could express this using Swift’s ownership model, eg. have LoggingCollector hold a reference to Collector during its lifetime, like the following
struct LoggingCollector: ~Copyable, ~Escapable {
var underlying: inout Collector
@_lifetime(&underlying)
init(underlying: inout Collector) {
self.underlying = underlying
}
@_lifetime(&self)
mutating func collect(data newData: String) {
print(newData)
underlying.collect(data: newData)
}
}For a real-world use case of this, look at https://github.com/vapor/postgres-nio/pull/573/files#diff-78fa91222207c0bc75d9f3a176984b69726754e569dd02a5eb52fad1146af2e5R107: ColumnWriter matches LoggingCollector and PostgresBinaryCopyFromWriter matches Collector in the reduced example above.
The approach mentioned above with UnsafeMutablePointer starts to break if Collector itself is a non-escapable type because we can’t form and UnsafeMutablePointer to it at that point anymore.