Short Array optimisation

All types simple or complex could implicitly conform to some built-in "ValueEnumerable" protocol:

extension UInt8: ValueEnumerable { // implicit
    static var possibleValueCount: Int { 256 }
}

enum ABC { case a, b c }
extension ABC: ValueEnumerable { // implicit
    static var possibleValueCount: Int { 3 }
}

enum TwoTier { case abc(ABC), d }
extension TwoTier: ValueEnumerable { // implicit
    static var possibleValueCount: Int { ABC.possibleValueCount + 1 }
}

typealias Pair = (ABC, UInt8)
// ditto for `struct Pair { var abc: ABC, uint8: UInt8 }`
extension Pair: ValueEnumerable {
    static var possibleValueCount: Int { ABC.possibleValueCount * UInt8.possibleValueCount }
}

extension Optional: ValueEnumerable { // implicit, don't use for references
    static var possibleValueCount: Int { 1 + Wrapped.possibleValueCount }
}

Similar to RawRepresentable ValueEnumerable might have an initialiser to go from "index" to the value:

protocol ValueEnumerable {
    static var possibleValueCount: Int { get }
    init(valueIndex: Int) -> Self
}

From there any interesting party (like Array) could determine the appropriate number of bits to store

Int(ceil(log2(TheType.possibleValueCount)))

References could be checked with special logic around the tagged pointers.


Or similar to what you said:

protocol BitRepresentable {
    var bitCount: Int? { get }
    init(_ bits: UnsafePointer<UInt8>, bitCount: Int)
    func toBits(_ bits: UnsafePointer<UInt8>, bitCount: Int)
}

I'm still very dubious as to the actual value of short array optimization in the general case, but I feel like the only thing we'd need for the UInt8 or bigger case would be BitwiseCopyable and an equivalent to C++s std:bit_cast. Especially since we are allowed to yield references to temporary values in _read & _modify accessors.

The cases for less than one byte objects would require a lot of new things to be even be potentially possible in a generic context: compile time execution of code, value generics, exposing sub-byte type layout to the programmer, (maybe) exposing niche values to the programmer.

3 Likes

What do you need from std::bit_cast that unsafeBitCast(_:to:) doesn't already do?

2 Likes

Nothing, I just forgot it existed.

3 Likes

Yeah, I was never able to get an idea like that past the "type metadata bloat police," most likely for good reason. But I wish you luck with that, and who knows, maybe things have changed.