Getting around unsafe pointer mutability requirements

Hi!

As a fun experiment, I wanted to see if I could make a "SmallArray" type that would have a fixed maximum size and not require a heap allocation. I wanted to make this type conform to RandomAccessCollection and also avoid having a bunch of branch instructions in my subscript operator.

This is what I tried:

struct SmallArray<Element>: RandomAccessCollection {
  var startIndex: Int { 0 }
  var endIndex: Int { _count }

  subscript(position: Int) -> Element {
    mutating get {
      precondition(indices.contains(position), "invalid index")
      withUnsafePointer(to: &_e0) { buffer in
        (buffer + position).pointee
      }
    }
  }
  internal var _count: Int
  internal var _e0, _e1, _e2, _e3, _e4, _e5: Element
}

I have to make the get accessor mutable to get at the _e0 pointer, but this breaks conformance for RandomAccessCollection. Hmm... Any tricks?

There's a non-inout version of withUnsafePointer, so you can drop the &. With that said, there's no guarantee* about struct memory layout, including that _e0, _e1, ... will be in that particular order. So it might not work as expected.

* There's a more limited version of the guarantee, about relation between value in a tuple, but I couldn't find it.

1 Like

That compiled. I missed it. My plan is to only refer to _e0 as the base address, but you are right. This is probably a horrible idea. Thank you!

Related thread: Fixed size array hacks

2 Likes

Oh cool. Thank you!