The difference in how you break things[1] as I see it is that usize
being pointer sized is one of the most normatively specified things in Rust.[2] Not only is that a bigger deal than breaking an assumption which was never promised, it penalizes the people who went to the effort to figure out, to the extent possible, what Rust's guarantees are. We should support those people, not penalize them.
It's not "just" the official documentation, although that's very important. RFC 0544 is the one that defined usize
. They are explicitly pointer-sized integers. Technically that was "just" a rename,[3] and you can see this was true before the rename (when they were int
/uint
) as well. They're also explicitly not ssize_t
/size_t
:
- The names fail to indicate the precise semantics of the types - pointer-sized integers.
[ ...]
- The names remind people of C's
ssize_t/size_t
, butisize/usize
don't share the exact same semantics with the C types.
RFCs and discussions around that time (which was the leadup to 1.0) include...
- Decide whether to keep pointer sized integers as the default
- RFC 161 (Closed)
- If `int` has the wrong size ...?
- RFC 464 (Closed)
- A tale of two's complement [4]
- Restarting the `int/uint` Discussion [5]
- RFC 0544 PR [6]
And if you read through them, the constant is that the type is pointer sized, and pointer sized is always "good enough" for indexing even if a smaller size would be more efficient.
It's also true of any issue on the topic I've seen post-stabilization.
RFC 1861 also defines pointers to externs to be usize
.
An undertone or presumption in the pre-1.0 discussion is that Rust should only have one signed/unsigned integer type where the width depends on the platform. In that world, the defining feature[7] has to be pointer width and not size_t
, because it's "good enough" for the other uses, while the opposite is not true.
Part of this issue is basically "opting for only one platform integer[8] was wrong", which I can empathize with. The problem with the proposal here is that size_t
is not the defining factor which has been promised, and people have -- reasonably and responsibly! -- relied on the definition.
I'm not convinced there isn't a way to change that definition in a way that blatantly breaks Rust's backwards compatibility promises, but anything I've thought of so far involves some sort of ecosystem split (like explicit opt-in, or crate-non-iteroperability across an edition).
usize
not pointer sized orusize
notsize_t
↩︎That's the definition any official place you look, should you choose to look. ↩︎
there was a ton of pre-stable contention around integers ↩︎
Excerpt:
int
anduint
are always defined to have the same number of bits as a pointer on the target platform[...]
it frequently happens that you have integers that are tied to the size of memory: for example, indices into an array or the size of an allocation. In these cases,
uint
andint
are an excellent choice, though it may make sense to use smaller, fixed-size types if you know that the length of the array (or size of the allocation, etc) is limited.-
it is certainly true that none of the listed proposals included variable-size integer types except for pointer-sized (and they all assume a flat address space as well). This is no accident.
-
On the other hand, seeing usize in the context of slice indexing or as the return of the len function is unlikely to lead to too much surprise for newcomers. A type like umem, on the other hand, is likely to raise eyebrows. Since "size" is general enough to refer to both the size of the address space and the size of a container and its indexes (which are, of course, closely related), and reasonably intuitive, we feel it is the best choice.
without committing to a stronger
size_t == uintptr_t
requirement ↩︎modulo signage ↩︎