Indexing slice with (Bound<usize>, Bound<usize>) may not get optimized property even with inline attribute.
Full compiler explorer: https://godbolt.org/z/96eoPsaTj
Simplest case
pub mod bounds_indexer {
use std::collections::Bound;
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 {
None
} else {
Some(&buf[(Bound::Included(4), Bound::Unbounded)])
}
}
}
Original case I initially working on, with impl RangeBounds
pub mod bounds_indexer_with_range_bounds {
// possible with stable
use std::ops::RangeBounds;
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 { None } else { Some(index(buf, 4..)) }
}
//#[inline(always)] // regardless. It looks rustc will inline this function without attribute
fn index(buf: &[u8], range: impl RangeBounds<usize>) -> &[u8] {
&buf[(range.start_bound().map(|x| *x), range.end_bound().map(|x| *x))]
}
}
Other complex cases with several ways to construct (Bound, Bound)
#![cfg_attr(feature="nightly", feature(range_into_bounds))]
#[cfg(feature="nightly")]
pub mod bounds_indexer_with_into_range_bounds {
// nigltly only requires #![feature(range_into_bounds)]
use std::ops::IntoBounds;
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 { None } else { Some(index(buf, 4..)) }
}
//#[inline(always)] // regardless. It looks rustc will inline this function without attribute
fn index(buf: &[u8], range: impl IntoBounds<usize>) -> &[u8] {
&buf[range.into_bounds()]
}
}
// Following is optimized and does not introduce bounds check if none of above two are not compiled.
// If either or both of above cases are compiled, `<(Bound<usize>, Bound<usize>) as SliceIndex<[u8]>>::index`
// will be called and bounds check will be ran in `SliceIndex::index`
pub mod bounds_indexer {
use std::collections::Bound;
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 {
None
} else {
Some(&buf[(Bound::Included(4), Bound::Unbounded)])
}
}
}
Following two cases get optimized out.
pub mod bounds_indexer_with_range_bounds_manually_mapped {
use std::collections::Bound;
use std::ops::RangeBounds;
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 { None } else { Some(index(buf, 4..)) }
}
fn index(buf: &[u8], range: impl RangeBounds<usize>) -> &[u8] {
&buf[match range.start_bound() {
Bound::Included(&i) => i,
Bound::Excluded(i) => i.checked_add(1).expect("overflow"),
Bound::Unbounded => 0,
}..match range.end_bound() {
Bound::Included(&i) => i,
Bound::Excluded(i) => i.checked_sub(1).expect("overflow"),
Bound::Unbounded => buf.len(),
}]
}
}
much shorter case
pub mod raw_index {
pub fn test(buf: &[u8]) -> Option<&[u8]> {
if buf.len() < 4 { None } else { Some(&buf[4..]) }
}
}
Surprisingly, Any of bad case will be optimized if only one of bad cases are compiled.
I think rustc can optimize indexing if there is only one <(Bound<usize>, Bound<usize>) as SliceIndex<[u8]>>::index invocation and can be inlined without almost no code size cost.
What's expected
I expected to see no bounds checks are emitted for all versions
Meta
rustc --version --verbose:
Basically testing with playground and compiler explorer
rustc 1.96.0 (ac68faa20 2026-05-25)
binary: rustc
commit-hash: ac68faa20c58cbccd01ee7208bf3b6e93a7d7f96
commit-date: 2026-05-25
host: x86_64-unknown-linux-gnu
release: 1.96.0
LLVM version: 22.1.2
Compiler returned: 0
Edit hisotry
- I found the Surprising part is not specific to the implementation, but for any implementation with
<(Bound<usize>, Bound<usize>) as SliceIndex<[u8]>>::index so modified accordingly with new fact
Indexing slice with
(Bound<usize>, Bound<usize>)may not get optimized property even with inline attribute.Full compiler explorer: https://godbolt.org/z/96eoPsaTj
Simplest case
Original case I initially working on, with impl RangeBounds
Other complex cases with several ways to construct (Bound, Bound)
Following two cases get optimized out.
much shorter case
Surprisingly, Any of bad case will be optimized if only one of bad cases are compiled.
I think rustc can optimize indexing if there is only one
<(Bound<usize>, Bound<usize>) as SliceIndex<[u8]>>::indexinvocation and can be inlined without almost no code size cost.What's expected
I expected to see no bounds checks are emitted for all versions
Meta
rustc --version --verbose:Basically testing with playground and compiler explorer
Edit hisotry
<(Bound<usize>, Bound<usize>) as SliceIndex<[u8]>>::indexso modified accordingly with new fact