-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
What it does
The following slice methods extract arrays from longer slices:
first_chunkandsplit_first_chunk(1.77, const 1.77)first_chunk_mutandsplit_first_chunk_mut(1.77, const 1.83)last_chunk(1.77, const 1.80) andsplit_last_chunk(1.77, const 1.77)last_chunk_mutandsplit_last_chunk_mut(1.77, const 1.83)
They're not always applicable, but if existing code is slicing or calling split_at[_*] with a constant index and then immediately turning the result into an array via TryInto, using one of the *_chunk APIs can be clearer about an array being involved. (Being careful about whether the array is a reference or a value, of course!)
Advantage
- Avoids using TryInto for a conversion that is infallible by construction.
- In many cases the
*_chunkAPIs allow omitting the array length entirely; it'll be inferrable from context. (As with all type inference, this could also be considered a disadvantage.)
Drawbacks
- There's no implicitly-panicking version of the
*_chunkAPIs, so even though there's no need to unwrap TryInto anymore, some of the transformations would introduce an explicit unwrap for the split point being in bounds. This can make the resulting code longer than the original code.
Example
// Before
u32::from_be_bytes(bytes[..4].try_into().unwrap())
// After
u32::from_be_bytes(*bytes.first_chunk().expect("slice is long enough"))// Before
u32::from_be_bytes(bytes.get(..4)?.try_into().unwrap())
// After
u32::from_be_bytes(*bytes.first_chunk()?)// Before
u32::from_be_bytes(bytes.get(bytes.len() - 4..)?.try_into().unwrap())
// After
u32::from_be_bytes(*bytes.last_chunk()?)// Before
let (magic_number, contents) = bytes.split_at_checked(8)?;
check(magic_number.try_into().unwrap());
// After
let (magic_number, contents) = bytes.split_first_chunk::<8>()?;
check(magic_number);// Before
let (contents, auth_tag) = bytes.split_at_mut(bytes.len() - 16);
cipher.write_auth_tag(auth_tag.try_into().unwrap());
// After
let (contents, auth_tag) = bytes.split_last_chunk_mut::<16>().expect("slice is long enough");
cipher.write_auth_tag(auth_tag);A possible extension to also cover copy_from_slice when copying from an array, for clearer code and an avoided (optimizable) bounds check:
// Before
let (magic_number, contents) = bytes.split_at_mut(8);
magic_number.copy_from_slice(&MAGIC_U32.to_be_bytes());
// After
let (magic_number, contents) = bytes.split_first_chunk_mut::<8>().expect("slice is long enough");
*magic_number = MAGIC_U32.to_be_bytes();Comparison with existing lints
No response
Additional Context
This operation is specifically interesting for pulling arrays out of slices. If someone wants to pull arrays out of arrays, the APIs in rust-lang/rust#90091 may be a better choice…but the ideal interface for those is blocked on stronger generic const exprs.