THe core::cmp::Ordering type has #[repr(u8)], but in cmp method we see the following code:
(*self as i32).cmp(&(*other as i32))
Why is the casting is not to u8?
>Solution :
Why is the casting is not to u8?
The first reason would be that Ordering‘s variants have the values -1, 0, and +1 so it would require an i8 to start with.
And although this was simply a replacement of int to i32, the reason why it’s remained i32 rather than be narrowed to i8 is the standard library integer usage guidelines:
- Use unsigned values if the value should always be greater than or equal to zero, and signed values otherwise.
- For indices, pointers, or other values which are tied to a data structure whose size is proportional to the size of memory, use usize or isize.
- For cases where the acceptable domain of a value perfectly fits a fixed number of bits, use the appropriate fixed-size type. For example, a method like write_u16 would take a u16 argument.
- Otherwise, use i32/u32 if the value has a narrow range and i64/u64 otherwise.
The examples specifically notes that this is a case were (3) doesn’t actually apply, not with this example but with a fairly close one:
The radix of an integer would use
u32. You might expectu8, since a radix higher than 256 is not useful, but the domain of useful radices is actually much smaller thanu8, so usingu8isn’t providing a meaningful guarantee, and will simply increase friction.
The exact same reasoning applies for ordering, it probably could have been an i8 but there was no reason to break the guidelines, and that might have required additional compiler work (as some platforms have only a subset of all operations below 32 bits e.g. ARM). Though one drawback is a possible issue for platforms with 16 bits registers, I don’t know if Rust supports or cares about those much (I know it supports pointers / addresses from 16 bits upwards, less sure for GPRs).