I don’t believe [[i32]]
support is really achievable, but it could be interesting to discuss some prior steps.
For example, ([i32], [i32])
- why doesn’t that work currently? I’d say two reasons. First, unsized fields currently must be the last field in a struct. Arguably, that rule could be changed though. (I’m not even 100% sure why it technically exists.) But then, second:multiple unsized fields would still be a significant problem, since you’d need to handle the metadata for two types.
That is, assuming that ([i32], [i32])
or struct Foo<S: ?Sized, T: ?Sized>(S, T)
does mean that the two slices have different lengths. (Would that also apply to struct Foo<T: ?Sized>(T, T)
? That seems… well… complicated, too.) The main issue with that is that pointer metadata currently all should be one usize
-word large. Though that needn’t be a law of nature either.
So if we had all of ()
, ([i32],)
, ([i32], [i32],)
, ([i32], [i32], [i32],)
, ([i32], [i32], [i32], [i32],)
, … then [[T]; N]
isn’t far off:
If we allow arbitrarily large metadata, and a one-metadata-per-value approach, then something like [[T]; N]
might be possible, where &[[T]; N]
would essentially have a metadata of type [usize; N]
encoding the lenghts. It’s debatable whether that should necessarily be the true array type [_; N]
, or better its own thing, so arrays can always keep the assumption that “offset-calculation is a simple ‘base + size * index’ calculation”. (This also, once again, runs into the design question of whether perhaps we want a [[T]; N]
-style type to actually mean that all contained slices can have different lengths, or if they should all be the same. Maybe we’d want to allow both possibilities – well yay, that’s two new ‘array’-like types then!)
[[i32]]
is still problematic then, though. (Except in the “this means all contained slices have the same size” interpretation.) If – due to metadata – the pointer types &[[i32]; 0]
, &[[i32]; 1]
, &[[i32]; 2]
, &[[i32]; 3]
, … all have different sizes, you cannot create values of a single type “&[[i32]]
” that unifies them all. Interestingly enough, if you consider something like ThinBox
, I’d say that - arguably - since in this world ThinBox<[[i32]; 0]>
, ThinBox<[[i32]; 1]>
, ThinBox<[[i32]; 2]>
, ThinBox<[[i32]; 3]>
, etc should all still have the same size, it’s not entirely unreasonable that perhaps ThinBox<[[i32]]>
could be made to work, somehow. That’s a lot of ifs… but maybe, maybe, this way [[i32]]
could have a (very limited) meaning after all? I don’t believe that this is something that we would ever want to pull off in Rust proper (and even if, I also think it should be its own kind of type, not literally using the existing “slice” type). Too complicated for too little benefit. Here’s my thoughs anyways:
It’d still require some additional language mechanisms. ThinBox<Ty>
’s API works in practice by creating &Ty
or &mut Ty
references for you (by loading the metadata from memory), but &[[i32]]
didn’t quite work, as discussed above. Well more technically, converting &[[i32]; N]
to some &[[i32]]
types doesn’t work. Maybe &[[i32]]
has a representation with metadata-behind-a-reference, i.e. somewhat of a &[usize]
metadata. This would preclude &'a [[i32]; N]
to &'a [[i32]]
conversions entirely; however it would still allow &'b &'a [[i32]; N]
to &'b [[i32]]
re-borrows, and also &'b ThinBox<[[i32]]>
to &'b [[i32]]
refererencing, I suppose.
There’s likely endless alternative language designs in this kind of direction of “assign some meaning to [[i32]
(or [[i32]; N]
or ([i32], [i32])
)”, and in any case, I’d say even support for something like ([i32], [i32])
is sufficiently nontrivial that we would likely want to focus entirely on that alone before generalizing any further.
Notably, ([i32], [i32])
seems somewhat desirable to me on its own, because with unsized-type function arguments (which already have unstable language support), a fn foo(x: [i32], y: [i32])
becomes possible but fn foo(x_and_y: ([i32], [i32]))
doesn’t, which is somewhat at odds with how we’d like to represent function argument lists as tuples in the Fn
traits.