Description
It's common knowledge that a "Rust object" or "Rust allocation" can't have a size which overflows isize
. This is relied upon in a lot of APIs such as the raw pointer add
method. However, the only place it seems to be documented as a general property is on the reference page for numeric types:
The
isize
type is a signed integer type with the same number of bits as the platform's pointer type. The theoretical upper bound on object and array size is the maximumisize
value. This ensures thatisize
can be used to calculate differences between pointers into an object or array and can address every byte within an object along with one byte past the end.
I see a few issues with this description:
- Being on the page for numeric types makes this text not that discoverable for people looking for general guarantees about types and allocations.
- It uses imprecise language: what are "objects" and "arrays"? Is the latter used in the sense of the type system - a
[T; N]
? - Some allocations are neither native Rust objects nor native Rust arrays. E.g., the allocation backing a
Vec
doesn't have a type (at least not in its API). If it's guaranteed that&T
can't refer to an object of more thanisize
bytes, thenvec.as_slice()
can't return a reference which violates this guarantee. However, that doesn't prevent the addresses ofvec[0]
andvec[N]
from being more thanisize
bytes apart. VariousVec
APIs strongly hint that this is impossible, but none actually guarantee it, and theVec
top-level docs make no guarantee about the interactions between various APIs (such as thevec[0]
/vec[N]
problem).
Based on my understanding of the current state of the language, here's a stab at a more complete set of guarantees; do these sound reasonable?
- For all
T
, givent: T
, the size oft
is guaranteed to fit in anisize
- For all
T
, givent: &T
, the size oft
's referent is guaranteed to fit in anisize
- With respect to non-builtin types like
Vec
, I could see a few approaches:- Each such type documents its own guarantees
- We define a formal notion of an "allocation", and document that
t: T
andt: &T
are instances of allocations. Beyond that, we leave it up to non-builtin types to document their own guarantees by making reference to the docs for "allocation". - We define a formal notion of an "allocation", and make it clear in the definition itself that it covers non-builtin things like
Vec
. That seems iffy; I'm not sure how you'd formally specify the set of objects that are covered by a definition like this (e.g., do we want to make guarantees about the memory backing aHashMap
?).
cc @jswrenn