Standard library noncopyable containers e.g Hypoarray

Hi all,

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.

You might want to check out the current WIP:

1 Like

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.