I think that's just an artefact of the way the methods on integer types are defined. It uses a macro where the pow method has been hard-coded as a u32.

This means that all integers expect to take a u32 as the exponent, it's even that way for i8 and u128.

It'd probably be more logical for all integers to use their unsigned variant as the exponent argument (u32 uses u32, i8 uses u8, etc), but fixing it now would break a lot of existing code and there was probably a good reason to do it that way in the first place.

Should signed integers also take a signed exponent?
(Edit: that was a rhetorical question)

Simply put, the base and the exponent play entirely different roles, and there is no reason for them to be the same type. u32 is the type that people are generally encouraged to use for "laughably small" unsigned integers, and exponents certainly fit that bill; all meaningful pow operations on rust primitive types today could be done even with a u8 exponent.

I'm puzzled by this on two fronts: a) on 32-bit systems (still fairly common), u32 won't be smaller than usize--they'll both be 32 bits, and b) what's the implication if u32is smaller than usize? I guess I'm not following the implied reasoning... (Personally, I'd have expected pow() to accept f64 or possibly usize; The u32 parameter surprised me as well).

Yes I wanted to restate it to make it obvious that u32 is not all the time smaller than usize, and see if there are more answers about that. I guess @Michael-F-Bryan 's explanation about an historical choice/design is accurate.

I spoke too quickly. What I mean is that, when I used the phrase "laughably small", I was referring to the value of size_of<usize>(), which is never larger than 64, and places an upper limit on meaningful values for the exponent.

Edit: Allow me to leave no room for interpretation:

2u64.pow(64) // thread 'main' panicked at 'attempt to multiply with overflow',