Replace offset with wrapping_offset
Currently we use offset in a number of crates. However, it is unsafe to use offset to implement an allocator because, according to the docs, "both the starting and resulting pointer must be either in bounds or one byte past the end of an allocated object."
Thus, we should switch to using wrapping_offset, which does not have this requirement.
According to the wrapping_offset docs, offset allows the compiler to make more aggressive optimizations, so we should be careful that this change does not regress performance.
It is not clear to me given the docs for offset and wrapping_offset that our uses of it are incorrect.
Except in cases where the caller passes an invalid pointer to free (which would result in Bad Things regardless of which offset method we use), I would consider any offset calls in the code resulting in a pointer to invalid (i.e. not mapped) memory to be a bug. Using wrapping_offset would not eliminate such a bug.
You might have a different interpretation of what the docs mean when they say "in bounds or one byte past the end..." than I do. I see this as meaning that we ensure pointers refer to valid/mapped memory even if that memory is an internal allocator data-structure. Indeed, we are generally careful to allocate any memory before we store a pointer to it; I don't see why memory being allocated using MmapAlloc should be considered beyond the pale when it implements Rust's (soon to be) standard allocation facility.
My intuition for this stems from the fact that the C standard has a similar provision for pointer arithmetic, and yet mallocs have historically (to my knowledge) been implemented in C using this facility.
Furthermore, the wrapping_offset docs do recommend offset as a superior default option.
This was inspired by this Rust issue. @kennytm may have thoughts on this.
To be clear, I think that in practice you're right that this will work, although I'm wary about relying on behavior that isn't guaranteed by the documentation.