Ohh
Conversation
This statement in the reference for "slice" is what I want, but also it is bad. Are there (safe) steps I can take to reliably ensure bounds-checking for a particular use of a slice is removed before runtime? Are the rules for this documented somewhere (such as the rustc manual)?
6
4
Like what I'm looking for is some way to type or decorate a site such that I'm asserting "I think I followed the rules to get a no-boundcheck optimization here, and if I messed up, I want the compiler to tell me so"
4
8
Several people replying "use iterators". Good approach, but here's a complication:
I often find myself in a situation where I have 2 arrays, incidentally of the same length.
int a:[T], b:[T];
I want to iterate over "both at once". For example produce a c such c[i] = a[i] + b[i]
1
7
Using the iterator syntax (which remember, I want to use because I want the language-level guarantee I'm avoiding bounds checks), is there a way to iterate over 2 arrays (or iterate up to end of shorter array)? In C I'd do this by iterating over key range and random indexing.
7
5
Replying to
Iterators are almost entirely library feature. The language provides some syntactic sugar via `for` loops.
The standard library's slice iterator has start and end pointers with the core iterator next method implemented as advancing by an element and comparing to the end pointer.
1
1
Replying to
If it happens to be the case that the standard library iterators will always follow the code path that removes the bounds checks at individual index sites, and this is a strong and universally understood social contract, that's "as good as" a lang guarantee for now i think
4
3
Yeah it's pretty widely understood in the community that if you're using iterators, you'll get bounds checks elided -- and any cases where that doesn't happen are a compiler bug
2
2
Yes, basically the use of an iterator allows the proof that the bounds will not be escaped to be done once, statically.
Sometimes adding an assert in the right place will also cause bounds checks later on to be elided/reduced.
1
2
It really depends on the iterator implementation. For the slice iterator (vectors included) it gets a start + end pointer at the start (no bounds check) and the next implementation is incrementing the pointer and doing a comparison between them each call.
Quote Tweet
Replying to @sgrif and @mcclure111
There aren't bounds checks to elide for the slice iterator. It's not that they're being elided but rather that the library implementation of the slice iterator uses a start and end pointer with unsafe code so you end up with the same kind of code as with a pair of C++ iterators.
1
It's an incredibly thin abstraction simply returning Option<T> with None indicating the end of iteration.
It also avoids overhead for some of the adaptors by not guaranteeing that it will keep returning None if you don't listen that it said it was over and you keep calling next.
The compiler will reliably inline everything and remove the obvious cruft. A lot of the less trivial adaptors like filter need their own loops inside their next() implementation. Definitely not guaranteed that it all gets optimized out but the core protocol is super efficient.



