Rfcs: Allow slicing to fixed-length arrays

Created on 28 Dec 2016  路  3Comments  路  Source: rust-lang/rfcs

I think it would be nice to do something like that:

let x = [1, 2, 3, 4];
let y = x[1..2];

Why isn't y of type [i32; 2] now?

I wanted to convert a [f32; 16] to an [[f32; 4]; 4], however there seems to be no easy way to do that.

T-lang

Most helpful comment

x[1..2] and x[1..4] are both calls to Trait std::ops::Index::<Range<usize>>::index. The type parameter Range<usize> is the same is both cases, therefore the associated type Index::Output has to be the same, therefore the return type of the index method has to be the same.

So it doesn鈥檛 work with the slicing/indexing syntax, but I agree that it would be nice to have some API that does this. However, doing it "right" likely requires type-lever integers. With made-up syntax, it could look like:

impl<T> [T] {
    pub fn as_array<int N>(&self) -> &[T; N] {
        assert_eq!(self.len(), N);
        let ptr = self.as_ptr() as *const [T; N];
        unsafe { &*ptr }
    }
}

In the meantime, you can fake it with a macro like the one used in ring.

I wanted to convert a [f32; 16] to an [[f32; 4]; 4]

If the size is fixed for your program that鈥檚 even easier. You can use a similar pattern, casting raw pointers:

fn to_4x4(array: &[f32; 16]) -> &[[f32; 4]; 4] {
    unsafe { &*(array as *const _ as *const _) }
}

However this case is more complicated than as_array above since the slice item type is not the same in and out.

All 3 comments

x[1..2] and x[1..4] are both calls to Trait std::ops::Index::<Range<usize>>::index. The type parameter Range<usize> is the same is both cases, therefore the associated type Index::Output has to be the same, therefore the return type of the index method has to be the same.

So it doesn鈥檛 work with the slicing/indexing syntax, but I agree that it would be nice to have some API that does this. However, doing it "right" likely requires type-lever integers. With made-up syntax, it could look like:

impl<T> [T] {
    pub fn as_array<int N>(&self) -> &[T; N] {
        assert_eq!(self.len(), N);
        let ptr = self.as_ptr() as *const [T; N];
        unsafe { &*ptr }
    }
}

In the meantime, you can fake it with a macro like the one used in ring.

I wanted to convert a [f32; 16] to an [[f32; 4]; 4]

If the size is fixed for your program that鈥檚 even easier. You can use a similar pattern, casting raw pointers:

fn to_4x4(array: &[f32; 16]) -> &[[f32; 4]; 4] {
    unsafe { &*(array as *const _ as *const _) }
}

However this case is more complicated than as_array above since the slice item type is not the same in and out.

Ah! Thanks for your solution. Yeah, it would be really handy to have these type-level integers.

Use the arrayref crate until we get type-level integers or similar.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

glaebhoerl picture glaebhoerl  路  112Comments

rust-highfive picture rust-highfive  路  75Comments

rust-highfive picture rust-highfive  路  103Comments

Centril picture Centril  路  90Comments

emk picture emk  路  59Comments