I am experimenting with building a small swift 6 package YogaSwift that wraps yoga (a c++ flexbox implementation).
I came across proposal-437 that has a sketch of Hypoarray, that eludes to building non copyable containers into the standard library in the future. Is it fair to say these won't land until at least a 6.1 swift release and that for now people should include their own version of Hypoarray?
My use case is that in my current implementation I'm using a ~Copyable type to wrap the yoga.YGNodeRef, that I can then free on deinit. I'm delegating the storage of children to the underlying YGNodeRef as I can't store an Array of my own non copyable type.
Ideally I'd like to build a tree of my own YGNode: ~Copyable types that I can traverse, which would let me drop the YGNodeView (~Copyable wrapper but doesn't free on deinit).
All thoughts and comments on the api design are very welcome.
Thanks @hassila for the link. I'll take a look at that.
I got something working on the hypoarray branch based of the example in the swift repo. I was hoping to stick to keeping the Node type as a protocol, but I'm hitting the limitation that I can't reassign to self after assigning to any Node & ~Copyable.
protocol Node: ~Copyable {
var children: Hypoarray<any Node & ~Copyable> { get set }
}
extension Node where Self: ~Copyable {
mutating func add(_ other: consuming some Node) {
// This works
children.append(other)
}
mutating func walk(_ closure: (inout any Node & ~Copyable) -> Void) {
var node: any Node & ~Copyable = self
closure(& node)
node.children.forEach { child in
child(closure)
}
/// This produces the below error in Swift 6 and main
self = node
}
}
~/YogaSwift/Sources/YogaSwift/Experiments.swift:129:12: error: cannot assign value of type 'any A & ~Copyable' to type 'Self'
127 | node.walk(closure)
128 | }
129 | self = a
| `- error: cannot assign value of type 'any A & ~Copyable' to type 'Self'
130 | }
131 | }
Changing the code to var a: Self = self
~/YogaSwift/Sources/YogaSwift/Experiments.swift:125:13: error: inout argument could be set to a value with a type other than 'Self'; use a value declared as type 'any A & ~Copyable' instead
122 |
123 | mutating func walk(_ closure: (inout any A & ~Copyable) -> Void) {
124 | var a: Self = self
| `- note: change variable type to 'any A & ~Copyable' if it doesn't need to be declared as 'Self'
125 | closure(&a)
| `- error: inout argument could be set to a value with a type other than 'Self'; use a value declared as type 'any A & ~Copyable' instead
126 | a.children.forEach { node in
127 | node.walk(closure)
[4/6] Compiling YogaSwift Experiments.swift
The error messages are really nice and make sense. I was wondering if there is a way to spell "you can mutate this but not replace it with a different node"?
In practice I can work around this by limiting the API to Self and not allowing people to define their own Node implementations.