(I'm back here after some hiatus).
I've seen that this code:
#[inline(never)]
pub fn foo1(ch: &[u8; 13]) -> ([u8; 5], [u8; 5]) {
let a = &ch[0 .. 5].try_into().unwrap();
let b = &ch[8 .. 13].try_into().unwrap();
(*a, *b)
}
Gives reasonable asm, but it contains some visible unwraps:
foo1:
mov rax, rdi
mov ecx, dword ptr [rsi]
movzx edx, byte ptr [rsi + 4]
mov edi, dword ptr [rsi + 8]
movzx esi, byte ptr [rsi + 12]
mov byte ptr [rax + 4], dl
mov dword ptr [rax], ecx
mov byte ptr [rax + 9], sil
mov dword ptr [rax + 5], edi
ret
This version is OK and it avoids the unwraps (and unsafe code) but it's a bit too much fiddly with many variable names:
#[inline(never)]
pub fn foo2(ch: &[u8; 13]) -> ([u8; 5], [u8; 5]) {
let &[a0,a1,a2,a3,a4, _,_,_, b0,b1,b2,b3,b4] = ch;
([a0, a1, a2, a3, a4], [b0, b1, b2, b3, b4])
}
This avoids that problem, using just few variables:
#[inline(never)]
pub fn foo3(ch: &[u8; 13]) -> ([u8; 5], [u8; 5]) {
let &[a@.., _,_,_, _,_,_,_,_] = ch;
let &[_,_,_,_,_, _,_,_, b@..] = ch;
(a, b)
}
But this (reasonable) version currently doesn't compile (two @.. aren't supported):
#[inline(never)]
pub fn foo4(ch: &[u8; 13]) -> ([u8; 5], [u8; 5]) {
let &[a@.., _,_,_, b@..] = ch;
(a, b)
}
So the question is, is it worth supporting this last version of the code too to slice & dice fixed-size arrays (not run-time-sized slices)?
With methods like .array_chunks()
I'm (finally) using more arrays in my Rust code.