Not sure how to proceed, since I may have created a generalized existential

I was writing a new version of a fixed-size array manifesto, and I got to the flatten-into-buffer functions:

func withFlattening<T: [... ; some Any], R>(of: T, body: (UnsafeBufferPointer<T.Element>) throws -> R) rethrows -> R

Then I finally realized that all the earlier parts of the report use FSA existentials another way:

let intArray: [3 ; Int] = [1, 2, 3]
let doubleArray: [2, 2 ; Double] = [1.0, 2.0, 3.0, 4.0]
var numericArray: [... ; some Numeric] = intArray
//...
numericArray = doubleArray

I was using a FSA existential as a variable's type instead of just a generic constraint. This second use is that "generalized existential" feature I've read about here, right? We currently don't have it. (We can't make a Numeric variable, let alone have it store Int and Double values at different times.)

Which brings up my problem. If we don't have generalized existentials now, then I probably shouldn't introduce a version of them in this manifesto. What if we add them later, but they have incompatibilities with the FSA ones? It would be better if I left them out, then when/if generalized existentials are added overall, everything would be consistent.

But some of the ideas already assume I can use FSA existentials as returnable types:

func extents<T: [... ; some Any]>(of a: T) -> [_ ; Int]

What would this return in a world where generalized existential values couldn't be returned?

func extents<T: [... ; some Any]>(of a: T) -> [#extentCountOf(T) ; Int]

could work, assuming we can't create constructs where the number of dimensions in T would only be known at run-time. Also, I think without FSA generalized existentials, we would have to design a AnyFSA<Element> type that works like AnySequence, AnyHashable, etc.

Or I could just go ahead and design generalized existentials for FSAs, and maybe we can later design any-type generalized existentials off my work. (There would still be consistency in this route.)

Would you please clarify what FSA means in this context?

Fixed-Sized Array(s)

2 Likes

A few hours later, I realized I could do:

func extents<T: [... ; some Any]>(of a: T) -> some [_ ; Int]

I'm not sure that would cause problems if the number of extents could only be determined at run-time. But, I'm not sure that would ever happen; maybe any use of FSAs would not throw away the extent count during compile time.

Right now, I restricted the use of FSA existentials to generic constraints. I uploaded the report to my Gist.