Conversation

Replying to and
It can't cheat by wrapping all the around and back into the same object. It's a bit silly that the safe one is called wrapping_add because allowing wrapping is only one of the things it allows. Note that ptr::wrapping_add is safe and ptr::add is unsafe due to the UB.
1
1
Replying to and
It's UB to deference a pointer outside the bounds of the object it was derived from regardless of which one you use. The purpose of ptr::add is that it's also undefined to create the pointer outside bounds of the object which enables optimizations even if load isn't right there.
1
Replying to
Main guarantees is that it's in-bound. ptr::wrapping_add method is poorly named. The main difference is that it permits the result to not be within the bounds of the object. Disallowing wrapping as part of inbounds is a bonus thing.
1
Replying to and
So, among many other things, it's guaranteed to not be a null pointer and null checks can be eliminated. A negative offset will go backwards within the object, a positive offset will go forwards within the object (up to one byte past the end) and a zero offset will stay the same.
2
Replying to
I'm listing out some of the properties guaranteed by inbounds GEP for optimizations. It's a much stricter variant of the usual C rules for signed integer arithmetic. It's the strict interpretation of the C standard's definition of pointer arithmetic used by Clang everywhere.
1
Replying to and
If you use -fwrapv, Clang will generate it without inbounds, so -fwrapv does more than just relaxing the signed integer arithmetic rules. Rust gives a choice for each case, with ptr::add being the usual approach. It's normal C-style pointer arithmetic. It's unusual to need more.
1
Replying to and
Rust defines the maximize size of an object as isize::MAX elsewhere, i.e. it would be undefined behavior to allocate an 2^31+1 byte object. It's hard to avoid it being undefined in C due to ptrdiff_t overflow being undefined, but it doesn't assign responsibility to avoid it.